Skip to content

Commit d881931

Browse files
panvanodejs-github-bot
authored andcommitted
crypto: map JWK export failures to OperationError
Map inaccessible key material to the Web Crypto error type, including seedless ML-DSA and ML-KEM keys converted from KeyObjects. Assisted-by: Codex Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: #66237 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
1 parent 642f172 commit d881931

2 files changed

Lines changed: 43 additions & 1 deletion

File tree

‎lib/internal/crypto/webcrypto.js‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,13 @@ function exportKeyJWK(key) {
806806
};
807807
if (alg === undefined) delete parameters.alg;
808808

809-
return getCryptoKeyHandle(key).exportJwk(parameters, true);
809+
try {
810+
return getCryptoKeyHandle(key).exportJwk(parameters, true);
811+
} catch (err) {
812+
throw lazyDOMException(
813+
'The operation failed for an operation-specific reason',
814+
{ name: 'OperationError', cause: err });
815+
}
810816
}
811817

812818
function exportKeySync(format, key) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
const { hasOpenSSL, isBoringSSL } = require('../common/crypto');
7+
if (isBoringSSL || !hasOpenSSL(3, 5))
8+
common.skip('requires OpenSSL 3.5 or later');
9+
10+
const assert = require('assert');
11+
const { createPrivateKey } = require('crypto');
12+
const fixtures = require('../common/fixtures');
13+
const { subtle } = globalThis.crypto;
14+
15+
(async () => {
16+
const algorithm = { name: 'AES-GCM', iv: new Uint8Array(12) };
17+
const wrappingKey = await subtle.generateKey({ name: 'AES-GCM', length: 128 },
18+
false, ['wrapKey']);
19+
for (const [name, usage] of [
20+
['ML-KEM-512', 'decapsulateBits'],
21+
['ML-KEM-768', 'decapsulateBits'],
22+
['ML-KEM-1024', 'decapsulateBits'],
23+
['ML-DSA-44', 'sign'],
24+
['ML-DSA-65', 'sign'],
25+
['ML-DSA-87', 'sign'],
26+
]) {
27+
const file = `${name.toLowerCase().replaceAll('-', '_')}_private_priv_only.pem`;
28+
const key = createPrivateKey(fixtures.readKey(file)).toCryptoKey(name, true, [usage]);
29+
await assert.rejects(subtle.exportKey('jwk', key), {
30+
name: 'OperationError', constructor: DOMException,
31+
});
32+
await assert.rejects(subtle.wrapKey('jwk', key, wrappingKey, algorithm), {
33+
name: 'OperationError', constructor: DOMException,
34+
});
35+
}
36+
})().then(common.mustCall());

0 commit comments

Comments
 (0)