The following code works in Firefox 76.0.1:
"use strict"
let RSAKeys
(async () => {
RSAKeys = await crypto.subtle.generateKey({
name: "RSA-OAEP",
modulusLength: 3072,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"},
true,
// Chromium bug causes it to falsely complain that the array is empty. Sometimes adding "encrypt" helps.
["wrapKey"])
})()
but in Chromium 80 I get:
Uncaught (in promise) DOMException: Usages cannot be empty when creating a key.
["wrapKey"] clearly isn't an empty array, so it seems to be a browser bug. Probably this one. Can you confirm? And more importantly, do you know a workaround? (Adding the encrypt usage helped but only the first time, then the same error.) It has to be an asymmetric cipher supporting wrapping keys. According to the table in the relevant chapter of the spec, RSA-OAEP is the only possibility.
I can reproduce the issue on Chromium version 85.0.4162.0: The key usage ["wrapKey"] generates the posted error message. But I can't reproduce that an adding of the key usage encrypt (i.e. ["wrapKey", "encrypt"]) solves the problem (not even the fist time). However, with the addition of the key usage unwrapKey (i.e. ["wrapKey", "unwrapKey"]) the error no longer occurs.
SubtleCrypto.generateKey() returns a CryptoKeyPair for "RSA-OAEP" that contains the RSA key pair. If you look in the Firefox browser console at the key pair generated with the key usage ["wrapKey", "unwrapKey"], you can see that the key usage of the public key is ["wrapKey"] and that of the private key is ["unwrapKey"]. Both are plausible, since the public key is used for wrapping and the private key for unwrapping:
However, if you look in the Firefox browser console at the key pair generated with the key usage ["wrapKey"], you can see that the key usage of the public key is unchanged ["wrapKey"], while that of the private key is empty:
So Chromium prevents the generation of a key without key usage by the corresponding error message (which obviously refers to the private key with the empty key usage). In contrast to Chromium, Firefox obviously allows this.
Now is that a Chromium bug? Actually it makes not much sense to create a key without a key usage, because it cannot be used!
Example for Firefox browser: If the following code is executed in the Firefox browser, the key pair is indeed generated and a key is wrapped because of the key usage wrapKey for the public key, but the unwrapping fails with an InvalidAccessError if the key usage unwrapKey for the private key is missing:
var test = async () => {
try {
var mode = document.querySelector('input[name="keyUsages"]:checked').value;
var keyUsages = (mode === "wrap") ? ["wrapKey"] : ["wrapKey", "unwrapKey"]
// Create RSA key pair
var RSAKeys = await crypto.subtle.generateKey(
{name: "RSA-OAEP", modulusLength: 3072, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: "SHA-256"}},
true,
keyUsages);
// Create key to wrap
var keyToWrap = await window.crypto.subtle.generateKey(
{name: "AES-GCM", length: 128},
true,
["encrypt", "decrypt"]);
// Wrap key
var wrappedKey = await window.crypto.subtle.wrapKey(
"raw",
keyToWrap,
RSAKeys.publicKey,
{name: "RSA-OAEP", hash: {name: "SHA-256"}});
// Unwrap key
var unwrappedKey = await window.crypto.subtle.unwrapKey(
"raw",
wrappedKey,
RSAKeys.privateKey,
{name: "RSA-OAEP", modulusLength: 3072, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: "SHA-256"}},
{name: "AES-GCM", length: 128},
false,
["encrypt", "decrypt"]);
document.getElementById("result").innerHTML = "Secret key for " + unwrappedKey.algorithm.name + " unwrapped.";
console.log(unwrappedKey);
} catch(e) {
document.getElementById("result").innerHTML = e.name + ": " + e.message;
}
}
.as-console-wrapper { max-height: 7.0em !important; }
<!DOCTYPE html>
<html>
<body height="200">
<input type="radio" name="keyUsages" value="wrap" checked="true"> ["wrapKey"]
<input type="radio" name="keyUsages" value="wrapUnwrap"> ["wrapKey", "unwrapKey"]
<button onclick="test()">Run</button><br/>
<p id="result"></p>
</body>
</html>
Therefore I would not classify this as a bug (but that's just my opinion).
Related
I'm making a discord bot but I'm trying to use 2 prefix's (G! and g!) as its case sensitive but I cant figure out how to make a 2nd prefix for it to work.
I have tried to separate strings with a comma between 2 strings but I got error codes.
DETECTS WETHER MESSAGE HAS PREFIX (IN DIFFERENT FILE)
module.exports = (client, message) => {
// Ignore all bots
if (message.author.bot) return;
// Ignore messages not starting with the prefix (in config.json)
if (message.content.indexOf(client.config.prefix) !== 0) return;
CONFIG FILE
{
"token": "xxx",
"prefix": "G!",
"prefix2": "g!",
"everyoneMention": true,
"hostedBy": true
}
Let's say i have 2 objects each with the same properties but one has an extra property middleName and the other does not.
How should i handle this in DC.js?
var objects = [{
name: "De Smet",
firstName: "Jasper",
adress: "Borsbeke",
},{
name: "De Backer",
firstName: "Dieter",
middleName: "middleName",
adress: "Borsbeke"
},{
name: "De Bondtr",
firstName: "Simon",
middleName: "OtherMiddleName",
adress: "Denderleeuw"
}
]
The wanted behaviour would be that the object without the property gets filtered out. Like so:
Here is a fiddle:
https://jsfiddle.net/mj92shru/41/
It seems to add the property middlename to the first object and assigns it the next middlename it finds
Adding the property to the first object and adding a placeholder value like "none" works but it doesnt really produce wanted behaviour.
I realize i could filter out the objects where the middlename is set to "none" but this would be difficult in the actual application i am writing
i've also found that adding the object without the property last causes it to crash.
Indeed, using undefined fields for your dimension or group keys can crash crossfilter because it does not validate its data. NaN, null, and undefined do not have well-defined sorting operations.
It's strange to see the value folded into another bin, but I suspect it's the same undefined behavior, rather than something you can depend on.
If you have fields which may be undefined, you should always default them, even if you don't want the value:
middleNameDimension = j.dimension(d => d.middleName || 'foo'),
I think you do want to filter your data, but not in the crossfilter sense where those rows are removed and do not influence other charts. Instead, it should just be removed from the group without affecting anything else.
You can use a "fake group" for this, and there is one in the FAQ which is suited perfectly for your problem:
function remove_bins(source_group) { // (source_group, bins...}
var bins = Array.prototype.slice.call(arguments, 1);
return {
all:function () {
return source_group.all().filter(function(d) {
return bins.indexOf(d.key) === -1;
});
}
};
}
Apply it like this:
.group(remove_bins(middleNameGroup, 'foo'))
Fork of your fiddle.
Be careful with this, because a pie chart implicitly adds up to 100%, and in this case it only adds up to 66%. This may be confusing for users, depending how it is used.
What is the relationship between the kid supplied to MediaKeySession.generateRequest() and the one provided via MediaKeyMessageEvent?
If they are supposed to be the same - why are they different in the code below? note, this won't run here due to security restrictions
navigator.requestMediaKeySystemAccess("org.w3.clearkey", [{
initDataTypes: ['webm'],
audioCapabilities: [{
contentType: 'audio/webm; codecs="opus"'
}],
videoCapabilities: [{
contentType: 'video/webm; codecs="vp8"'
},
{
contentType: 'video/webm; codecs="vp9"'
}
],
}]).then((keySystemAccess) => {
return keySystemAccess.createMediaKeys();
}).then((mediaKeys) => {
var session = mediaKeys.createSession("temporary");
var keyId = "VHM2iIMGiSg";
var initData = '{"kids":["' + keyId + '"]}';
console.log(keyId);
session.addEventListener('message', (evt) => {
var requestJson = new TextDecoder().decode(evt.message);
var request = JSON.parse(requestJson);
console.log(request.kids[0]);
});
this.session.generateRequest("webm", new TextEncoder().encode(initData));
});
output:
VHM2iIMGiSg
eyJraWRzIjpbIlZITTJpSU1HaVNnIl19
expected output is for second line to also be VHM2iIMGiSg
eyJraWRzIjpbIlZITTJpSU1HaVNnIl19 is the base64url encoded value of initData that was passed to generateRequest.
The reason that request.kids[0] is the full value of initData and not the value of keyId is because generateRequest was invoked with the initDataType parameter set to webm. Had the initDataType parameter been set to keyids then request.kids[0] would be the value of keyId.
When the initDataType parameter is set to webm the initData parameter is expected to be a single key ID of one or more bytes. Whereas when the initDataType parameter is set to keyids the initData parameter is expected to be a JSON object encoded as UTF-8, containing a single member kids which is an array of base64url encoded Key ID(s).
I am using sequelize ORM with mySQL database.
I have a model with attribute type TEXT as :
description: {
type: Sequelize.TEXT,
unique: true
},
When I am trying to create table for the corresponding model, its giving an error message as :
Unhandled rejection SequelizeDatabaseError:
ER_BLOB_KEY_WITHOUT_LENGTH: BLOB/TEXT column 'description' used in key
specification without a key length
This worked fine when used with postgreSQL.
Possible reason for this error which i could think of can be that mySQL doesn't support TEXT datatype and therefore, i have to specify it as LONGTEXT.
If I am thinking correct or is there some other reason for the same, if someone can help.
You are using unique: true with data-type TEXT. You can not use it. Do you delete unique: true and try again?
esmrkbr is correct, mySQL does not accept UNIQUE KEY on a TEXT field, you need to use VARCHAR instead (see: make text column as unique key). That being said, depending on the Database being used, you may need to explicitly specify a size for a TEXT (or BLOB) type. The documentation (http://docs.sequelizejs.com/en/latest/api/datatypes/) is pretty terse on this point and other than a link to the code, currently only has the following information:
An (un)limited length text column. Available lengths: tiny, medium,
long
You can pass the size as a string argument to the type. For example, to have it defined as LONGTEXT you will need:
description: {
type: Sequelize.TEXT('long')
},
The code in lib/data-types.js has the following mapping to SQL for TEXT (there is a similar one for BLOB also):
TEXT.prototype.toSql = function() {
switch (this._length.toLowerCase()) {
case 'tiny':
return 'TINYTEXT';
case 'medium':
return 'MEDIUMTEXT';
case 'long':
return 'LONGTEXT';
default:
return this.key;
}
};
Define as string like this:
var filters = sequelize.define('filters', {
description: {
type: DataTypes.STRING,
validate: { notEmpty: true }
}
}
I was just working on some tests for Local Storage in HTML5. Note I used Safari 6.0.2, as it seems many web-engines handle their methods different.
If I do this:
localStorage.setItem('subTotal', Number(12345)); // I know, it's redundant :)
var varType = typeof localStorage.getItem('subTotal');
alert(varType);
You would now think; It's a Number!. But no it's not.. It seems, even with type casting, that HTML5 Local Storage converts all variable types to Strings when inserting them. It's funny tho, because when using the Development Tools it shows String values between quotes, but not the Numbers. Maybe it's the Inspector pane that strips the quotes tho.
I already have an old automatic typeCasting function in jQuery, yet I'm always weary of these cases, as 0 and false, can still make a mess of things.
Anyone know if the localStorage.* Library has a setting to maintain the Variable Types?
You should convert them to JSON first:
localStorage.setItem( 'subTotal', JSON.stringify(12345) );
Then, when retrieving your item, parse the JSON:
JSON.parse( localStorage.getItem('subTotal') );
Here's the fiddle: http://jsfiddle.net/hD9dF/
For easier usage, create your own wrapper:
var myLocalStorage = {
set: function (item, value) {
localStorage.setItem( item, JSON.stringify(value) );
},
get: function (item) {
return JSON.parse( localStorage.getItem(item) );
}
};
Here's the fiddle: http://jsfiddle.net/hD9dF/1/
Local storage converts everything to string (as it saves everything as text).
To make your life easier, and at least preserve number/boolean/object structure, JSON.stringify and JSON.parse everything that goes in and out.
And to improve performance of that suggestion, only use one localStorage variable per "concept" (like all data for a map widget, or all user-preferences, etc), and build a JS object which you then turn into a JSON string, to save to that one variable (when necessary).
What you want to do is simple with localDataStorage, where you can transparently set/get any of the following "types": Array, Boolean, Date, Float, Integer, Null, Object or String.
[DISCLAIMER] I am the author of the utility [/DISCLAIMER]
Examples:
localDataStorage.set( 'key1', 'Belgian' );
localDataStorage.set( 'key2', 1200.0047 );
localDataStorage.set( 'key3', true );
localDataStorage.set( 'key4', { 'RSK' : [1,'3',5,'7',9] } );
localDataStorage.set( 'key5', null );
localDataStorage.get( 'key1' ); --> 'Belgian'
localDataStorage.get( 'key2' ); --> 1200.0047
localDataStorage.get( 'key3' ); --> true
localDataStorage.get( 'key4' ); --> Object {RSK: Array(5)}
localDataStorage.get( 'key5' ); --> null
All of the conversion work is done in the background for you: just set and get.
Example:
let id = JSON.parse(<any>localStorage.getItem("id"))
if (typeof id != "number") {
// rest of code