Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6cc4cf8

Browse filesBrowse files
panvaRafaelGSS
authored andcommitted
crypto: unify asymmetric key import through KeyObjectHandle::Init
Consolidate all asymmetric key import paths (DER/PEM, JWK, raw) into a single KeyObjectHandle::Init() entry point with a uniform signature. Remove the per-type C++ init methods (InitECRaw, InitEDRaw, InitPqcRaw, InitJwk, InitECPrivateRaw) and their JS-side callers, replacing them with shared C++ and JS helpers. createPublicKey, createPrivateKey, sign, verify, and other operations that accept key material now handle JWK and raw formats directly in C++, removing redundant JS-to-C++ key handle round-trips. Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: #62499 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent b81d2cb commit 6cc4cf8
Copy full SHA for 6cc4cf8

25 files changed

+929-1,065Lines changed: 929 additions & 1065 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎lib/internal/crypto/aes.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/aes.js
+8-23Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const {
1010
AESCipherJob,
1111
KeyObjectHandle,
1212
kCryptoJobAsync,
13+
kKeyFormatJWK,
14+
kKeyTypeSecret,
1315
kKeyVariantAES_CTR_128,
1416
kKeyVariantAES_CBC_128,
1517
kKeyVariantAES_GCM_128,
@@ -30,7 +32,6 @@ const {
3032
const {
3133
hasAnyNotIn,
3234
jobPromise,
33-
validateKeyOps,
3435
kHandle,
3536
kKeyObject,
3637
} = require('internal/crypto/util');
@@ -47,6 +48,10 @@ const {
4748
kAlgorithm,
4849
} = require('internal/crypto/keys');
4950

51+
const {
52+
validateJwk,
53+
} = require('internal/crypto/webcrypto_util');
54+
5055
const {
5156
generateKey: _generateKey,
5257
} = require('internal/crypto/keygen');
@@ -245,31 +250,11 @@ function aesImportKey(
245250
break;
246251
}
247252
case 'jwk': {
248-
if (!keyData.kty)
249-
throw lazyDOMException('Invalid keyData', 'DataError');
250-
251-
if (keyData.kty !== 'oct')
252-
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
253-
254-
if (usagesSet.size > 0 &&
255-
keyData.use !== undefined &&
256-
keyData.use !== 'enc') {
257-
throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError');
258-
}
259-
260-
validateKeyOps(keyData.key_ops, usagesSet);
261-
262-
if (keyData.ext !== undefined &&
263-
keyData.ext === false &&
264-
extractable === true) {
265-
throw lazyDOMException(
266-
'JWK "ext" Parameter and extractable mismatch',
267-
'DataError');
268-
}
253+
validateJwk(keyData, 'oct', extractable, usagesSet, 'enc');
269254

270255
const handle = new KeyObjectHandle();
271256
try {
272-
handle.initJwk(keyData);
257+
handle.init(kKeyTypeSecret, keyData, kKeyFormatJWK, null, null);
273258
} catch (err) {
274259
throw lazyDOMException(
275260
'Invalid keyData', { name: 'DataError', cause: err });
Collapse file

‎lib/internal/crypto/cfrg.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/cfrg.js
+20-137Lines changed: 20 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,22 @@ const {
66
TypedArrayPrototypeGetBuffer,
77
} = primordials;
88

9-
const { Buffer } = require('buffer');
10-
119
const {
12-
KeyObjectHandle,
1310
SignJob,
1411
kCryptoJobAsync,
1512
kKeyFormatDER,
16-
kKeyTypePrivate,
17-
kKeyTypePublic,
13+
kKeyFormatRawPublic,
1814
kSignJobModeSign,
1915
kSignJobModeVerify,
2016
kWebCryptoKeyFormatPKCS8,
2117
kWebCryptoKeyFormatRaw,
2218
kWebCryptoKeyFormatSPKI,
2319
} = internalBinding('crypto');
2420

25-
const {
26-
codes: {
27-
ERR_CRYPTO_INVALID_JWK,
28-
},
29-
} = require('internal/errors');
30-
3121
const {
3222
getUsagesUnion,
3323
hasAnyNotIn,
3424
jobPromise,
35-
validateKeyOps,
3625
kHandle,
3726
kKeyObject,
3827
} = require('internal/crypto/util');
@@ -48,13 +37,16 @@ const {
4837

4938
const {
5039
InternalCryptoKey,
51-
PrivateKeyObject,
52-
PublicKeyObject,
53-
createPrivateKey,
54-
createPublicKey,
5540
kKeyType,
5641
} = require('internal/crypto/keys');
5742

43+
const {
44+
importDerKey,
45+
importJwkKey,
46+
importRawKey,
47+
validateJwk,
48+
} = require('internal/crypto/webcrypto_util');
49+
5850
const generateKeyPair = promisify(_generateKeyPair);
5951

6052
function verifyAcceptableCfrgKeyUse(name, isPublic, usages) {
@@ -81,39 +73,6 @@ function verifyAcceptableCfrgKeyUse(name, isPublic, usages) {
8173
}
8274
}
8375

84-
function createCFRGRawKey(name, keyData, isPublic) {
85-
const handle = new KeyObjectHandle();
86-
87-
switch (name) {
88-
case 'Ed25519':
89-
case 'X25519':
90-
if (keyData.byteLength !== 32) {
91-
throw lazyDOMException(
92-
`${name} raw keys must be exactly 32-bytes`, 'DataError');
93-
}
94-
break;
95-
case 'Ed448':
96-
if (keyData.byteLength !== 57) {
97-
throw lazyDOMException(
98-
`${name} raw keys must be exactly 57-bytes`, 'DataError');
99-
}
100-
break;
101-
case 'X448':
102-
if (keyData.byteLength !== 56) {
103-
throw lazyDOMException(
104-
`${name} raw keys must be exactly 56-bytes`, 'DataError');
105-
}
106-
break;
107-
}
108-
109-
const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate;
110-
if (!handle.initEDRaw(name, keyData, keyType)) {
111-
throw lazyDOMException('Invalid keyData', 'DataError');
112-
}
113-
114-
return isPublic ? new PublicKeyObject(handle) : new PrivateKeyObject(handle);
115-
}
116-
11776
async function cfrgGenerateKey(algorithm, extractable, keyUsages) {
11877
const { name } = algorithm;
11978

@@ -243,113 +202,36 @@ function cfrgImportKey(
243202
}
244203
case 'spki': {
245204
verifyAcceptableCfrgKeyUse(name, true, usagesSet);
246-
try {
247-
keyObject = createPublicKey({
248-
key: keyData,
249-
format: 'der',
250-
type: 'spki',
251-
});
252-
} catch (err) {
253-
throw lazyDOMException(
254-
'Invalid keyData', { name: 'DataError', cause: err });
255-
}
205+
keyObject = importDerKey(keyData, true);
256206
break;
257207
}
258208
case 'pkcs8': {
259209
verifyAcceptableCfrgKeyUse(name, false, usagesSet);
260-
try {
261-
keyObject = createPrivateKey({
262-
key: keyData,
263-
format: 'der',
264-
type: 'pkcs8',
265-
});
266-
} catch (err) {
267-
throw lazyDOMException(
268-
'Invalid keyData', { name: 'DataError', cause: err });
269-
}
210+
keyObject = importDerKey(keyData, false);
270211
break;
271212
}
272213
case 'jwk': {
273-
if (!keyData.kty)
274-
throw lazyDOMException('Invalid keyData', 'DataError');
275-
if (keyData.kty !== 'OKP')
276-
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
214+
const expectedUse = (name === 'X25519' || name === 'X448') ? 'enc' : 'sig';
215+
validateJwk(keyData, 'OKP', extractable, usagesSet, expectedUse);
216+
277217
if (keyData.crv !== name)
278218
throw lazyDOMException(
279219
'JWK "crv" Parameter and algorithm name mismatch', 'DataError');
280-
const isPublic = keyData.d === undefined;
281-
282-
if (usagesSet.size > 0 && keyData.use !== undefined) {
283-
let checkUse;
284-
switch (name) {
285-
case 'Ed25519':
286-
// Fall through
287-
case 'Ed448':
288-
checkUse = 'sig';
289-
break;
290-
case 'X25519':
291-
// Fall through
292-
case 'X448':
293-
checkUse = 'enc';
294-
break;
295-
}
296-
if (keyData.use !== checkUse)
297-
throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError');
298-
}
299-
300-
validateKeyOps(keyData.key_ops, usagesSet);
301-
302-
if (keyData.ext !== undefined &&
303-
keyData.ext === false &&
304-
extractable === true) {
305-
throw lazyDOMException(
306-
'JWK "ext" Parameter and extractable mismatch',
307-
'DataError');
308-
}
309220

310221
if (keyData.alg !== undefined && (name === 'Ed25519' || name === 'Ed448')) {
311-
if (keyData.alg !== name && keyData.alg !== 'EdDSA') {
222+
if (keyData.alg !== name && keyData.alg !== 'EdDSA')
312223
throw lazyDOMException(
313-
'JWK "alg" does not match the requested algorithm',
314-
'DataError');
315-
}
224+
'JWK "alg" does not match the requested algorithm', 'DataError');
316225
}
317226

318-
if (!isPublic && typeof keyData.x !== 'string') {
319-
throw lazyDOMException('Invalid JWK', 'DataError');
320-
}
321-
322-
verifyAcceptableCfrgKeyUse(
323-
name,
324-
isPublic,
325-
usagesSet);
326-
327-
try {
328-
const publicKeyObject = createCFRGRawKey(
329-
name,
330-
Buffer.from(keyData.x, 'base64'),
331-
true);
332-
333-
if (isPublic) {
334-
keyObject = publicKeyObject;
335-
} else {
336-
keyObject = createCFRGRawKey(
337-
name,
338-
Buffer.from(keyData.d, 'base64'),
339-
false);
340-
341-
if (!createPublicKey(keyObject).equals(publicKeyObject)) {
342-
throw new ERR_CRYPTO_INVALID_JWK();
343-
}
344-
}
345-
} catch (err) {
346-
throw lazyDOMException('Invalid keyData', { name: 'DataError', cause: err });
347-
}
227+
const isPublic = keyData.d === undefined;
228+
verifyAcceptableCfrgKeyUse(name, isPublic, usagesSet);
229+
keyObject = importJwkKey(isPublic, keyData);
348230
break;
349231
}
350232
case 'raw': {
351233
verifyAcceptableCfrgKeyUse(name, true, usagesSet);
352-
keyObject = createCFRGRawKey(name, keyData, true);
234+
keyObject = importRawKey(true, keyData, kKeyFormatRawPublic, name);
353235
break;
354236
}
355237
default:
@@ -381,6 +263,7 @@ async function eddsaSignVerify(key, data, algorithm, signature) {
381263
undefined,
382264
undefined,
383265
undefined,
266+
undefined,
384267
data,
385268
undefined,
386269
undefined,
Collapse file

‎lib/internal/crypto/chacha20_poly1305.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/chacha20_poly1305.js
+8-23Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ const {
99
ChaCha20Poly1305CipherJob,
1010
KeyObjectHandle,
1111
kCryptoJobAsync,
12+
kKeyFormatJWK,
13+
kKeyTypeSecret,
1214
} = internalBinding('crypto');
1315

1416
const {
1517
hasAnyNotIn,
1618
jobPromise,
17-
validateKeyOps,
1819
kHandle,
1920
kKeyObject,
2021
} = require('internal/crypto/util');
@@ -30,6 +31,10 @@ const {
3031
createSecretKey,
3132
} = require('internal/crypto/keys');
3233

34+
const {
35+
validateJwk,
36+
} = require('internal/crypto/webcrypto_util');
37+
3338
const {
3439
randomBytes: _randomBytes,
3540
} = require('internal/crypto/random');
@@ -107,31 +112,11 @@ function c20pImportKey(
107112
break;
108113
}
109114
case 'jwk': {
110-
if (!keyData.kty)
111-
throw lazyDOMException('Invalid keyData', 'DataError');
112-
113-
if (keyData.kty !== 'oct')
114-
throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
115-
116-
if (usagesSet.size > 0 &&
117-
keyData.use !== undefined &&
118-
keyData.use !== 'enc') {
119-
throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError');
120-
}
121-
122-
validateKeyOps(keyData.key_ops, usagesSet);
123-
124-
if (keyData.ext !== undefined &&
125-
keyData.ext === false &&
126-
extractable === true) {
127-
throw lazyDOMException(
128-
'JWK "ext" Parameter and extractable mismatch',
129-
'DataError');
130-
}
115+
validateJwk(keyData, 'oct', extractable, usagesSet, 'enc');
131116

132117
const handle = new KeyObjectHandle();
133118
try {
134-
handle.initJwk(keyData);
119+
handle.init(kKeyTypeSecret, keyData, kKeyFormatJWK, null, null);
135120
} catch (err) {
136121
throw lazyDOMException(
137122
'Invalid keyData', { name: 'DataError', cause: err });
Collapse file

‎lib/internal/crypto/cipher.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/cipher.js
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const { StringDecoder } = require('string_decoder');
6464

6565
function rsaFunctionFor(method, defaultPadding, keyType) {
6666
return (options, buffer) => {
67-
const { format, type, data, passphrase } =
67+
const { format, type, data, passphrase, namedCurve } =
6868
keyType === 'private' ?
6969
preparePrivateKey(options) :
7070
preparePublicOrPrivateKey(options);
@@ -76,8 +76,8 @@ function rsaFunctionFor(method, defaultPadding, keyType) {
7676
if (oaepLabel !== undefined)
7777
oaepLabel = getArrayBufferOrView(oaepLabel, 'key.oaepLabel', encoding);
7878
buffer = getArrayBufferOrView(buffer, 'buffer', encoding);
79-
return method(data, format, type, passphrase, buffer, padding, oaepHash,
80-
oaepLabel);
79+
return method(data, format, type, passphrase, namedCurve, buffer,
80+
padding, oaepHash, oaepLabel);
8181
};
8282
}
8383

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.