diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index 70e1027946190a..13db3d24dc63a6 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -772,6 +772,10 @@ const kKeyOps = { unwrapKey: 6, deriveKey: 7, deriveBits: 8, + encapsulateKey: 9, + encapsulateBits: 10, + decapsulateKey: 11, + decapsulateBits: 12, }; function validateKeyOps(keyOps, usagesSet) { diff --git a/test/parallel/test-webcrypto-export-import-ml-kem.js b/test/parallel/test-webcrypto-export-import-ml-kem.js index 9b75dee64511d9..1da0218f258e3c 100644 --- a/test/parallel/test-webcrypto-export-import-ml-kem.js +++ b/test/parallel/test-webcrypto-export-import-ml-kem.js @@ -491,3 +491,16 @@ async function testImportJwk({ name, publicUsages, privateUsages }, extractable) }); } })().then(common.mustCall()); + +// Regression test: JWK `key_ops` validation must recognize ML-KEM operations +// (encapsulateKey, encapsulateBits, decapsulateKey, decapsulateBits) so that +// duplicate entries are rejected +(async function() { + for (const op of ['encapsulateKey', 'encapsulateBits', + 'decapsulateKey', 'decapsulateBits']) { + const jwk = { ...keyData['ML-KEM-768'].jwk, key_ops: [op, op] }; + await assert.rejects( + subtle.importKey('jwk', jwk, { name: 'ML-KEM-768' }, true, [op]), + { name: 'DataError', message: /Duplicate key operation/ }); + } +})().then(common.mustCall());