Implement key length constraints
This commit is contained in:
Родитель
3eb64528f3
Коммит
927e6b93fc
|
@ -14,18 +14,23 @@ const ACTIVE_DURATION = 1000 * 60 * 5;
|
|||
const KDF_ENC = 'cookiesession-encryption';
|
||||
const KDF_MAC = 'cookiesession-signature';
|
||||
|
||||
const ENCRYPTION_ALGORITHMS = [
|
||||
'aes128', // implicit CBC mode
|
||||
'aes192',
|
||||
'aes256'
|
||||
];
|
||||
/* map from cipher algorithm to exact key byte length */
|
||||
const ENCRYPTION_ALGORITHMS = {
|
||||
aes128: 16, // implicit CBC mode
|
||||
aes192: 24,
|
||||
aes256: 32
|
||||
};
|
||||
const DEFAULT_ENCRYPTION_ALGO = 'aes256';
|
||||
|
||||
const SIGNATURE_ALGORITHMS = [
|
||||
'sha256', 'sha256-drop128',
|
||||
'sha384', 'sha384-drop192',
|
||||
'sha512', 'sha512-drop256'
|
||||
];
|
||||
/* map from hmac algorithm to _minimum_ key byte length */
|
||||
const SIGNATURE_ALGORITHMS = {
|
||||
'sha256': 32,
|
||||
'sha256-drop128': 32,
|
||||
'sha384': 48,
|
||||
'sha384-drop192': 48,
|
||||
'sha512': 64,
|
||||
'sha512-drop256': 64
|
||||
};
|
||||
const DEFAULT_SIGNATURE_ALGO = 'sha256';
|
||||
|
||||
function isObject(val) {
|
||||
|
@ -94,6 +99,37 @@ function setupKeys(opts) {
|
|||
}
|
||||
}
|
||||
|
||||
function keyConstraints(opts) {
|
||||
if (!Buffer.isBuffer(opts.encryptionKey)) {
|
||||
throw new Error('encryptionKey must be a Buffer');
|
||||
}
|
||||
if (!Buffer.isBuffer(opts.signatureKey)) {
|
||||
throw new Error('signatureKey must be a Buffer');
|
||||
}
|
||||
|
||||
if (constantTimeEquals(opts.encryptionKey, opts.signatureKey)) {
|
||||
throw new Error('Encryption and Signature keys must be different');
|
||||
}
|
||||
|
||||
var encAlgo = opts.encryptionAlgorithm;
|
||||
var required = ENCRYPTION_ALGORITHMS[encAlgo];
|
||||
if (opts.encryptionKey.length !== required) {
|
||||
throw new Error(
|
||||
'Encryption Key for '+encAlgo+' must be exactly '+required+' bytes '+
|
||||
'('+(required*8)+' bits)'
|
||||
);
|
||||
}
|
||||
|
||||
var sigAlgo = opts.signatureAlgorithm;
|
||||
var minimum = SIGNATURE_ALGORITHMS[sigAlgo];
|
||||
if (opts.signatureKey.length < minimum) {
|
||||
throw new Error(
|
||||
'Encryption Key for '+sigAlgo+' must be at least '+minimum+' bytes '+
|
||||
'('+(minimum*8)+' bits)'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function constantTimeEquals(a, b) {
|
||||
// Ideally this would be a native function, so it's less sensitive to how the
|
||||
// JS engine might optimize.
|
||||
|
@ -475,7 +511,6 @@ Object.defineProperty(Session.prototype, 'content', {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
function clientSessionFactory(opts) {
|
||||
if (!opts) {
|
||||
throw new Error("no options provided, some are required");
|
||||
|
@ -494,17 +529,17 @@ function clientSessionFactory(opts) {
|
|||
|
||||
var encAlg = opts.encryptionAlgorithm || DEFAULT_ENCRYPTION_ALGO;
|
||||
encAlg = encAlg.toLowerCase();
|
||||
if (ENCRYPTION_ALGORITHMS.indexOf(encAlg) === -1) {
|
||||
if (!ENCRYPTION_ALGORITHMS[encAlg]) {
|
||||
throw new Error('invalid encryptionAlgorithm, supported are: '+
|
||||
ENCRYPTION_ALGORITHMS.join(', '));
|
||||
Object.keys(ENCRYPTION_ALGORITHMS).join(', '));
|
||||
}
|
||||
opts.encryptionAlgorithm = encAlg;
|
||||
|
||||
var sigAlg = opts.signatureAlgorithm || DEFAULT_SIGNATURE_ALGO;
|
||||
sigAlg = sigAlg.toLowerCase();
|
||||
if (SIGNATURE_ALGORITHMS.indexOf(sigAlg) === -1) {
|
||||
if (!SIGNATURE_ALGORITHMS[sigAlg]) {
|
||||
throw new Error('invalid signatureAlgorithm, supported are: '+
|
||||
SIGNATURE_ALGORITHMS.join(', '));
|
||||
Object.keys(SIGNATURE_ALGORITHMS).join(', '));
|
||||
}
|
||||
opts.signatureAlgorithm = sigAlg;
|
||||
|
||||
|
@ -523,6 +558,7 @@ function clientSessionFactory(opts) {
|
|||
*/
|
||||
|
||||
setupKeys(opts);
|
||||
keyConstraints(opts);
|
||||
|
||||
const propertyName = opts.requestKey || opts.cookieName;
|
||||
|
||||
|
|
|
@ -1186,33 +1186,34 @@ suite.addBatch({
|
|||
}
|
||||
});
|
||||
|
||||
var sixtyFourByteKey = new Buffer(
|
||||
'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||
'binary'
|
||||
);
|
||||
var HMAC_EXPECT = {
|
||||
// aligned so you can see the dropN effect:
|
||||
'sha256':
|
||||
'ib46vUCBTNOcEl9P6dRwlxZNGNQMHDMulJEc+sAcET8=',
|
||||
'PRYaxV/8RkMyIT/Ib+tIUOWiSn+0EvodJ5rtG1FQHz0=',
|
||||
'sha256-drop128':
|
||||
'ib46vUCBTNOcEl9P6dRwlw==',
|
||||
'PRYaxV/8RkMyIT/Ib+tIUA==',
|
||||
'sha384':
|
||||
'JRnBFUT/W+/EjpBdWmQ/hctq1g1/IUaD6Sqyi9qGH4R2a8uv+86vZXvY72fYNTYw',
|
||||
'MND9nz6pxbQC5m41ZPRXhJIuqTj9/hu4gtWZ8t8LgdFLQFWQfC8jhijB0NHLpeA7',
|
||||
'sha384-drop192':
|
||||
'JRnBFUT/W+/EjpBdWmQ/hctq1g1/IUaD',
|
||||
'MND9nz6pxbQC5m41ZPRXhJIuqTj9/hu4',
|
||||
'sha512':
|
||||
'l4D3LI09OMccrCXQcXl/biDZM1t1yDHEqZbz5DXb1IxUnX956imItOBuJu/bP0Zr'+
|
||||
'wzWl2vJxNvOBWpfdA9xl4Q==',
|
||||
'Hr4KLVLyglIwQ43C9U2bmieWBVLnD/F+lzCSF072Ds2b87MK+gbnR0p75A+I+5ez+aiemMGuMZyKVAUWfMMaUA==',
|
||||
'sha512-drop256':
|
||||
'l4D3LI09OMccrCXQcXl/biDZM1t1yDHEqZbz5DXb1Iw='
|
||||
'Hr4KLVLyglIwQ43C9U2bmieWBVLnD/F+lzCSF072Ds0='
|
||||
};
|
||||
|
||||
function testHmac(algo) {
|
||||
var block = {};
|
||||
block.topic = function() {
|
||||
var sixteen = new Buffer('0123456789abcdef','binary');
|
||||
|
||||
var opts = {
|
||||
signatureAlgorithm: algo,
|
||||
signatureKey: sixteen
|
||||
signatureKey: sixtyFourByteKey
|
||||
};
|
||||
var iv = sixteen;
|
||||
var iv = new Buffer('01234567890abcdef','binary'); // 128-bits
|
||||
var ciphertext = new Buffer('0123456789abcdef0123','binary');
|
||||
var duration = 876543210;
|
||||
var createdAt = 1234567890;
|
||||
|
|
Загрузка…
Ссылка в новой задаче