crypto: reject duplicate unknown key usages

Check all JWK key_ops entries for duplicates before ignoring unknown
usage names.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
This commit is contained in:
Filip Skokan authored and Node.js GitHub Bot committed 2026-09-25 13:23:14 +00:00
1 parent 7c20a5c587
commit ff6027d487
2 files changed
+24 -3

No files matched your search

+4 -3
View File
@@ -1220,15 +1220,16 @@ function validateKeyOps(keyOps, usagesSet) {
if (keyOps === undefined) return;
validateArray(keyOps, 'keyData.key_ops');
let keyOpsMask = 0;
const seen = new SafeSet();
for (let n = 0; n < keyOps.length; n++) {
const op = keyOps[n];
if (seen.has(op))
throw lazyDOMException('Duplicate key operation', 'DataError');
seen.add(op);
const opMask = kUsageMasks[op];
// Skipping unknown key ops
if (opMask === undefined)
continue;
// Have we seen it already? if so, error
if (keyOpsMask & opMask)
throw lazyDOMException('Duplicate key operation', 'DataError');
keyOpsMask |= opMask;
// TODO(@jasnell): RFC7517 section 4.3 strong recommends validating
@@ -0,0 +1,20 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const { subtle } = globalThis.crypto;
(async () => {
const algorithm = { name: 'HMAC', hash: 'SHA-256' };
const jwk = { kty: 'oct', k: 'AAAAAAAAAAAAAAAAAAAAAA' };
await subtle.importKey('jwk', { ...jwk, key_ops: ['sign', 'future'] },
algorithm, false, ['sign']);
for (const key_ops of [['sign', 'sign'], ['sign', 'future', 'future']]) {
await assert.rejects(subtle.importKey('jwk', { ...jwk, key_ops },
algorithm, false, ['sign']),
{ name: 'DataError' });
}
})().then(common.mustCall());