crypto: fix webcrypto HMAC "get key length" in deriveKey and generateKey

PR-URL: https://github.com/nodejs/node/pull/44917
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
pull/44250/head
Filip Skokan 2022-10-12 21:18:38 +02:00 committed by GitHub
parent 40a0757b21
commit 214354fc9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 26 deletions

View File

@ -14,7 +14,7 @@ const {
} = internalBinding('crypto');
const {
getHashLength,
getBlockSize,
hasAnyNotIn,
jobPromise,
normalizeHashName,
@ -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);

View File

@ -340,12 +340,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;
}
}
@ -430,8 +430,8 @@ module.exports = {
validateMaxBufferLength,
bigIntArrayToUnsignedBigInt,
bigIntArrayToUnsignedInt,
getBlockSize,
getStringOption,
getUsagesUnion,
getHashLength,
secureHeapUsed,
};

View File

@ -56,6 +56,7 @@ const {
const {
getArrayBufferOrView,
getBlockSize,
hasAnyNotIn,
lazyRequire,
normalizeAlgorithm,
@ -200,16 +201,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) {

View File

@ -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 () => {
@ -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) {

View File

@ -551,10 +551,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;
}
}