Skip to content

Commit 6cc4cf8

Browse 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

25 files changed

Lines changed: 929 additions & 1065 deletions

‎lib/internal/crypto/aes.js‎

Lines 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-
throwlazyDOMException('Invalid keyData','DataError');
250-
251-
if(keyData.kty!=='oct')
252-
throwlazyDOMException('Invalid JWK "kty" Parameter','DataError');
253-
254-
if(usagesSet.size>0&&
255-
keyData.use!==undefined&&
256-
keyData.use!=='enc'){
257-
throwlazyDOMException('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-
throwlazyDOMException(
266-
'JWK "ext" Parameter and extractable mismatch',
267-
'DataError');
268-
}
253+
validateJwk(keyData,'oct',extractable,usagesSet,'enc');
269254

270255
consthandle=newKeyObjectHandle();
271256
try{
272-
handle.initJwk(keyData);
257+
handle.init(kKeyTypeSecret,keyData,kKeyFormatJWK,null,null);
273258
}catch(err){
274259
throwlazyDOMException(
275260
'Invalid keyData',{name: 'DataError',cause: err});

‎lib/internal/crypto/cfrg.js‎

Lines 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
constgenerateKeyPair=promisify(_generateKeyPair);
5951

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

84-
functioncreateCFRGRawKey(name,keyData,isPublic){
85-
consthandle=newKeyObjectHandle();
86-
87-
switch(name){
88-
case'Ed25519':
89-
case'X25519':
90-
if(keyData.byteLength!==32){
91-
throwlazyDOMException(
92-
`${name} raw keys must be exactly 32-bytes`,'DataError');
93-
}
94-
break;
95-
case'Ed448':
96-
if(keyData.byteLength!==57){
97-
throwlazyDOMException(
98-
`${name} raw keys must be exactly 57-bytes`,'DataError');
99-
}
100-
break;
101-
case'X448':
102-
if(keyData.byteLength!==56){
103-
throwlazyDOMException(
104-
`${name} raw keys must be exactly 56-bytes`,'DataError');
105-
}
106-
break;
107-
}
108-
109-
constkeyType=isPublic ? kKeyTypePublic : kKeyTypePrivate;
110-
if(!handle.initEDRaw(name,keyData,keyType)){
111-
throwlazyDOMException('Invalid keyData','DataError');
112-
}
113-
114-
returnisPublic ? newPublicKeyObject(handle) : newPrivateKeyObject(handle);
115-
}
116-
11776
asyncfunctioncfrgGenerateKey(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-
throwlazyDOMException(
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-
throwlazyDOMException(
268-
'Invalid keyData',{name: 'DataError',cause: err});
269-
}
210+
keyObject=importDerKey(keyData,false);
270211
break;
271212
}
272213
case'jwk': {
273-
if(!keyData.kty)
274-
throwlazyDOMException('Invalid keyData','DataError');
275-
if(keyData.kty!=='OKP')
276-
throwlazyDOMException('Invalid JWK "kty" Parameter','DataError');
214+
constexpectedUse=(name==='X25519'||name==='X448') ? 'enc' : 'sig';
215+
validateJwk(keyData,'OKP',extractable,usagesSet,expectedUse);
216+
277217
if(keyData.crv!==name)
278218
throwlazyDOMException(
279219
'JWK "crv" Parameter and algorithm name mismatch','DataError');
280-
constisPublic=keyData.d===undefined;
281-
282-
if(usagesSet.size>0&&keyData.use!==undefined){
283-
letcheckUse;
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-
throwlazyDOMException('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-
throwlazyDOMException(
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
throwlazyDOMException(
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&&typeofkeyData.x!=='string'){
319-
throwlazyDOMException('Invalid JWK','DataError');
320-
}
321-
322-
verifyAcceptableCfrgKeyUse(
323-
name,
324-
isPublic,
325-
usagesSet);
326-
327-
try{
328-
constpublicKeyObject=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-
thrownewERR_CRYPTO_INVALID_JWK();
343-
}
344-
}
345-
}catch(err){
346-
throwlazyDOMException('Invalid keyData',{name: 'DataError',cause: err});
347-
}
227+
constisPublic=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,

‎lib/internal/crypto/chacha20_poly1305.js‎

Lines 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-
throwlazyDOMException('Invalid keyData','DataError');
112-
113-
if(keyData.kty!=='oct')
114-
throwlazyDOMException('Invalid JWK "kty" Parameter','DataError');
115-
116-
if(usagesSet.size>0&&
117-
keyData.use!==undefined&&
118-
keyData.use!=='enc'){
119-
throwlazyDOMException('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-
throwlazyDOMException(
128-
'JWK "ext" Parameter and extractable mismatch',
129-
'DataError');
130-
}
115+
validateJwk(keyData,'oct',extractable,usagesSet,'enc');
131116

132117
consthandle=newKeyObjectHandle();
133118
try{
134-
handle.initJwk(keyData);
119+
handle.init(kKeyTypeSecret,keyData,kKeyFormatJWK,null,null);
135120
}catch(err){
136121
throwlazyDOMException(
137122
'Invalid keyData',{name: 'DataError',cause: err});

‎lib/internal/crypto/cipher.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const { StringDecoder } = require('string_decoder');
6464

6565
functionrsaFunctionFor(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-
returnmethod(data,format,type,passphrase,buffer,padding,oaepHash,
80-
oaepLabel);
79+
returnmethod(data,format,type,passphrase,namedCurve,buffer,
80+
padding,oaepHash,oaepLabel);
8181
};
8282
}
8383

0 commit comments

Comments
 (0)