Skip to content
/ node Public
forked from nodejs/node

Commit

Permalink
crypto: fix webcrypto HMAC "get key length" in deriveKey and generateKey
Browse files Browse the repository at this point in the history
PR-URL: nodejs#44917
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Backport-PR-URL: nodejs#47336
  • Loading branch information
panva committed Mar 31, 2023
1 parent 5b9738a commit ae600b9
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 26 deletions.
4 changes: 2 additions & 2 deletions lib/internal/crypto/mac.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const {
} = internalBinding('crypto');

const {
getHashLength,
getBlockSize,
hasAnyNotIn,
jobPromise,
normalizeHashName,
Expand Down Expand Up @@ -54,7 +54,7 @@ async function hmacGenerateKey(algorithm, extractable, keyUsages) {
throw new ERR_MISSING_OPTION('algorithm.hash');

if (length === undefined)
length = getHashLength(hash.name);
length = getBlockSize(hash.name);

validateBitLength(length, 'algorithm.length', true);

Expand Down
12 changes: 6 additions & 6 deletions lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,12 +346,12 @@ function getUsagesUnion(usageSet, ...usages) {
return newset;
}

function getHashLength(name) {
function getBlockSize(name) {
switch (name) {
case 'SHA-1': return 160;
case 'SHA-256': return 256;
case 'SHA-384': return 384;
case 'SHA-512': return 512;
case 'SHA-1': return 512;
case 'SHA-256': return 512;
case 'SHA-384': return 1024;
case 'SHA-512': return 1024;
}
}

Expand Down Expand Up @@ -436,8 +436,8 @@ module.exports = {
validateMaxBufferLength,
bigIntArrayToUnsignedBigInt,
bigIntArrayToUnsignedInt,
getBlockSize,
getStringOption,
getUsagesUnion,
getHashLength,
secureHeapUsed,
};
12 changes: 2 additions & 10 deletions lib/internal/crypto/webcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const {

const {
getArrayBufferOrView,
getBlockSize,
hasAnyNotIn,
lazyRequire,
normalizeAlgorithm,
Expand Down Expand Up @@ -195,16 +196,7 @@ function getKeyLength({ name, length, hash }) {
return length;
case 'HMAC':
if (length === undefined) {
switch (hash?.name) {
case 'SHA-1':
return 160;
case 'SHA-256':
return 256;
case 'SHA-384':
return 384;
case 'SHA-512':
return 512;
}
return getBlockSize(hash?.name);
}

if (typeof length === 'number' && length !== 0) {
Expand Down
31 changes: 27 additions & 4 deletions test/parallel/test-webcrypto-derivekey.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ const { webcrypto: { subtle }, KeyObject } = require('crypto');
const vectors = [
['PBKDF2', 'deriveKey', 528],
['HKDF', 'deriveKey', 528],
[{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 160],
[{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 256],
[{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 384],
[{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 512],
[{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 512],
[{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 512],
// Not long enough secret generated by ECDH
// [{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 1024],
// [{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 1024],
];

(async () => {
Expand All @@ -151,6 +152,28 @@ const { webcrypto: { subtle }, KeyObject } = require('crypto');
})().then(common.mustCall());
}

{
const vectors = [
[{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 512],
[{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 512],
[{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 1024],
[{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 1024],
];

(async () => {
for (const [derivedKeyAlgorithm, usage, expected] of vectors) {
const derived = await subtle.deriveKey(
{ name: 'PBKDF2', salt: new Uint8Array([]), hash: 'SHA-256', iterations: 20 },
await subtle.importKey('raw', new Uint8Array([]), { name: 'PBKDF2' }, false, ['deriveKey']),
derivedKeyAlgorithm,
false,
[usage]);

assert.strictEqual(derived.algorithm.length, expected);
}
})().then(common.mustCall());
}

// Test X25519 and X448 key derivation
{
async function test(name) {
Expand Down
8 changes: 4 additions & 4 deletions test/parallel/test-webcrypto-keygen.js
Original file line number Diff line number Diff line change
Expand Up @@ -556,10 +556,10 @@ const vectors = {

if (length === undefined) {
switch (hash) {
case 'SHA-1': length = 160; break;
case 'SHA-256': length = 256; break;
case 'SHA-384': length = 384; break;
case 'SHA-512': length = 512; break;
case 'SHA-1': length = 512; break;
case 'SHA-256': length = 512; break;
case 'SHA-384': length = 1024; break;
case 'SHA-512': length = 1024; break;
}
}

Expand Down

0 comments on commit ae600b9

Please sign in to comment.