Skip to content

Commit 7f2258f

Browse files
committed
crypto: fix webcrypto HMAC "get key length" in deriveKey and generateKey
1 parent 4d94be3 commit 7f2258f

File tree

5 files changed

+47
-26
lines changed

5 files changed

+47
-26
lines changed

lib/internal/crypto/mac.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const {
1414
} = internalBinding('crypto');
1515

1616
const {
17-
getHashLength,
17+
getBlockSize,
1818
hasAnyNotIn,
1919
jobPromise,
2020
normalizeHashName,
@@ -54,7 +54,7 @@ async function hmacGenerateKey(algorithm, extractable, keyUsages) {
5454
throw new ERR_MISSING_OPTION('algorithm.hash');
5555

5656
if (length === undefined)
57-
length = getHashLength(hash.name);
57+
length = getBlockSize(hash.name);
5858

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

lib/internal/crypto/util.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,12 @@ function getUsagesUnion(usageSet, ...usages) {
341341
return newset;
342342
}
343343

344-
function getHashLength(name) {
344+
function getBlockSize(name) {
345345
switch (name) {
346-
case 'SHA-1': return 160;
347-
case 'SHA-256': return 256;
348-
case 'SHA-384': return 384;
349-
case 'SHA-512': return 512;
346+
case 'SHA-1': return 512;
347+
case 'SHA-256': return 512;
348+
case 'SHA-384': return 1024;
349+
case 'SHA-512': return 1024;
350350
}
351351
}
352352

@@ -431,8 +431,8 @@ module.exports = {
431431
validateMaxBufferLength,
432432
bigIntArrayToUnsignedBigInt,
433433
bigIntArrayToUnsignedInt,
434+
getBlockSize,
434435
getStringOption,
435436
getUsagesUnion,
436-
getHashLength,
437437
secureHeapUsed,
438438
};

lib/internal/crypto/webcrypto.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const {
5656

5757
const {
5858
getArrayBufferOrView,
59+
getBlockSize,
5960
hasAnyNotIn,
6061
lazyRequire,
6162
normalizeAlgorithm,
@@ -200,16 +201,7 @@ function getKeyLength({ name, length, hash }) {
200201
return length;
201202
case 'HMAC':
202203
if (length === undefined) {
203-
switch (hash?.name) {
204-
case 'SHA-1':
205-
return 160;
206-
case 'SHA-256':
207-
return 256;
208-
case 'SHA-384':
209-
return 384;
210-
case 'SHA-512':
211-
return 512;
212-
}
204+
return getBlockSize(hash?.name);
213205
}
214206

215207
if (typeof length === 'number' && length !== 0) {

test/parallel/test-webcrypto-derivekey.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,11 @@ const { webcrypto: { subtle }, KeyObject } = require('crypto');
124124
const vectors = [
125125
['PBKDF2', 'deriveKey', 528],
126126
['HKDF', 'deriveKey', 528],
127-
[{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 160],
128-
[{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 256],
129-
[{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 384],
130-
[{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 512],
127+
[{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 512],
128+
[{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 512],
129+
// Not long enough secret generated by ECDH
130+
// [{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 1024],
131+
// [{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 1024],
131132
];
132133

133134
(async () => {
@@ -151,6 +152,34 @@ const { webcrypto: { subtle }, KeyObject } = require('crypto');
151152
})().then(common.mustCall());
152153
}
153154

155+
{
156+
const vectors = [
157+
[{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 512],
158+
[{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 512],
159+
[{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 1024],
160+
[{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 1024],
161+
];
162+
163+
(async () => {
164+
for (const [derivedKeyAlgorithm, usage, expected] of vectors) {
165+
const derived = await subtle.deriveKey(
166+
{ name: 'PBKDF2', salt: new Uint8Array([]), hash: 'SHA-256', iterations: 20 },
167+
await subtle.importKey('raw', new Uint8Array([]), { name: 'PBKDF2' }, false, ['deriveKey']),
168+
derivedKeyAlgorithm,
169+
false,
170+
[usage]);
171+
172+
if (derived.algorithm.name === 'HMAC') {
173+
assert.strictEqual(derived.algorithm.length, expected);
174+
} else {
175+
// KDFs cannot be exportable and do not indicate their length
176+
const secretKey = KeyObject.from(derived);
177+
assert.strictEqual(secretKey.symmetricKeySize, expected / 8);
178+
}
179+
}
180+
})().then(common.mustCall());
181+
}
182+
154183
// Test X25519 and X448 key derivation
155184
{
156185
async function test(name) {

test/parallel/test-webcrypto-keygen.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,10 +551,10 @@ const vectors = {
551551

552552
if (length === undefined) {
553553
switch (hash) {
554-
case 'SHA-1': length = 160; break;
555-
case 'SHA-256': length = 256; break;
556-
case 'SHA-384': length = 384; break;
557-
case 'SHA-512': length = 512; break;
554+
case 'SHA-1': length = 512; break;
555+
case 'SHA-256': length = 512; break;
556+
case 'SHA-384': length = 1024; break;
557+
case 'SHA-512': length = 1024; break;
558558
}
559559
}
560560

0 commit comments

Comments
 (0)