33const {
44 SafeSet,
55 StringPrototypeToLowerCase,
6+ TypedArrayPrototypeGetBuffer,
67} = primordials ;
78
89const { Buffer } = require ( 'buffer' ) ;
910
1011const {
11- ECKeyExportJob,
12- KeyObjectHandle,
1312 SignJob,
1413 kCryptoJobAsync,
15- kKeyTypePrivate ,
16- kKeyTypePublic ,
14+ kKeyFormatDER ,
15+ kKeyFormatRawPublic ,
1716 kSignJobModeSign,
1817 kSignJobModeVerify,
18+ kWebCryptoKeyFormatPKCS8,
19+ kWebCryptoKeyFormatRaw,
20+ kWebCryptoKeyFormatSPKI,
1921} = internalBinding ( 'crypto' ) ;
2022
21- const {
22- codes : {
23- ERR_CRYPTO_INVALID_JWK ,
24- } ,
25- } = require ( 'internal/errors' ) ;
26-
2723const {
2824 getUsagesUnion,
2925 hasAnyNotIn,
3026 jobPromise,
31- validateKeyOps,
3227 kHandle,
3328 kKeyObject,
3429} = require ( 'internal/crypto/util' ) ;
@@ -44,13 +39,16 @@ const {
4439
4540const {
4641 InternalCryptoKey,
47- PrivateKeyObject,
48- PublicKeyObject,
49- createPrivateKey,
50- createPublicKey,
5142 kKeyType,
5243} = require ( 'internal/crypto/keys' ) ;
5344
45+ const {
46+ importDerKey,
47+ importJwkKey,
48+ importRawKey,
49+ validateJwk,
50+ } = require ( 'internal/crypto/webcrypto_util' ) ;
51+
5452const generateKeyPair = promisify ( _generateKeyPair ) ;
5553
5654function verifyAcceptableCfrgKeyUse ( name , isPublic , usages ) {
@@ -77,39 +75,6 @@ function verifyAcceptableCfrgKeyUse(name, isPublic, usages) {
7775 }
7876}
7977
80- function createCFRGRawKey ( name , keyData , isPublic ) {
81- const handle = new KeyObjectHandle ( ) ;
82-
83- switch ( name ) {
84- case 'Ed25519' :
85- case 'X25519' :
86- if ( keyData . byteLength !== 32 ) {
87- throw lazyDOMException (
88- `${ name } raw keys must be exactly 32-bytes` , 'DataError' ) ;
89- }
90- break ;
91- case 'Ed448' :
92- if ( keyData . byteLength !== 57 ) {
93- throw lazyDOMException (
94- `${ name } raw keys must be exactly 57-bytes` , 'DataError' ) ;
95- }
96- break ;
97- case 'X448' :
98- if ( keyData . byteLength !== 56 ) {
99- throw lazyDOMException (
100- `${ name } raw keys must be exactly 56-bytes` , 'DataError' ) ;
101- }
102- break ;
103- }
104-
105- const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate ;
106- if ( ! handle . initEDRaw ( name , keyData , keyType ) ) {
107- throw lazyDOMException ( 'Invalid keyData' , 'DataError' ) ;
108- }
109-
110- return isPublic ? new PublicKeyObject ( handle ) : new PrivateKeyObject ( handle ) ;
111- }
112-
11378async function cfrgGenerateKey ( algorithm , extractable , keyUsages ) {
11479 const { name } = algorithm ;
11580
@@ -171,7 +136,7 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) {
171136 case 'X25519' :
172137 // Fall through
173138 case 'X448' :
174- publicUsages = new SafeSet ( ) ;
139+ publicUsages = [ ] ;
175140 privateUsages = getUsagesUnion ( usageSet , 'deriveKey' , 'deriveBits' ) ;
176141 break ;
177142 }
@@ -196,10 +161,29 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) {
196161}
197162
198163function cfrgExportKey ( key , format ) {
199- return jobPromise ( ( ) => new ECKeyExportJob (
200- kCryptoJobAsync ,
201- format ,
202- key [ kKeyObject ] [ kHandle ] ) ) ;
164+ try {
165+ switch ( format ) {
166+ case kWebCryptoKeyFormatRaw : {
167+ const handle = key [ kKeyObject ] [ kHandle ] ;
168+ return TypedArrayPrototypeGetBuffer (
169+ key [ kKeyType ] === 'private' ? handle . rawPrivateKey ( ) : handle . rawPublicKey ( ) ) ;
170+ }
171+ case kWebCryptoKeyFormatSPKI : {
172+ return TypedArrayPrototypeGetBuffer (
173+ key [ kKeyObject ] [ kHandle ] . export ( kKeyFormatDER , kWebCryptoKeyFormatSPKI ) ) ;
174+ }
175+ case kWebCryptoKeyFormatPKCS8 : {
176+ return TypedArrayPrototypeGetBuffer (
177+ key [ kKeyObject ] [ kHandle ] . export ( kKeyFormatDER , kWebCryptoKeyFormatPKCS8 , null , null ) ) ;
178+ }
179+ default :
180+ return undefined ;
181+ }
182+ } catch ( err ) {
183+ throw lazyDOMException (
184+ 'The operation failed for an operation-specific reason' ,
185+ { name : 'OperationError' , cause : err } ) ;
186+ }
203187}
204188
205189function cfrgImportKey (
@@ -220,113 +204,42 @@ function cfrgImportKey(
220204 }
221205 case 'spki' : {
222206 verifyAcceptableCfrgKeyUse ( name , true , usagesSet ) ;
223- try {
224- keyObject = createPublicKey ( {
225- key : keyData ,
226- format : 'der' ,
227- type : 'spki' ,
228- } ) ;
229- } catch ( err ) {
230- throw lazyDOMException (
231- 'Invalid keyData' , { name : 'DataError' , cause : err } ) ;
232- }
207+ keyObject = importDerKey ( keyData , true ) ;
233208 break ;
234209 }
235210 case 'pkcs8' : {
236211 verifyAcceptableCfrgKeyUse ( name , false , usagesSet ) ;
237- try {
238- keyObject = createPrivateKey ( {
239- key : keyData ,
240- format : 'der' ,
241- type : 'pkcs8' ,
242- } ) ;
243- } catch ( err ) {
244- throw lazyDOMException (
245- 'Invalid keyData' , { name : 'DataError' , cause : err } ) ;
246- }
212+ keyObject = importDerKey ( keyData , false ) ;
247213 break ;
248214 }
249215 case 'jwk' : {
250- if ( ! keyData . kty )
251- throw lazyDOMException ( 'Invalid keyData' , 'DataError' ) ;
252- if ( keyData . kty !== 'OKP' )
253- throw lazyDOMException ( 'Invalid JWK "kty" Parameter' , 'DataError' ) ;
216+ const expectedUse = ( name === 'X25519' || name === 'X448' ) ? 'enc' : 'sig' ;
217+ validateJwk ( keyData , 'OKP' , extractable , usagesSet , expectedUse ) ;
218+
254219 if ( keyData . crv !== name )
255220 throw lazyDOMException (
256221 'JWK "crv" Parameter and algorithm name mismatch' , 'DataError' ) ;
257- const isPublic = keyData . d === undefined ;
258-
259- if ( usagesSet . size > 0 && keyData . use !== undefined ) {
260- let checkUse ;
261- switch ( name ) {
262- case 'Ed25519' :
263- // Fall through
264- case 'Ed448' :
265- checkUse = 'sig' ;
266- break ;
267- case 'X25519' :
268- // Fall through
269- case 'X448' :
270- checkUse = 'enc' ;
271- break ;
272- }
273- if ( keyData . use !== checkUse )
274- throw lazyDOMException ( 'Invalid JWK "use" Parameter' , 'DataError' ) ;
275- }
276-
277- validateKeyOps ( keyData . key_ops , usagesSet ) ;
278-
279- if ( keyData . ext !== undefined &&
280- keyData . ext === false &&
281- extractable === true ) {
282- throw lazyDOMException (
283- 'JWK "ext" Parameter and extractable mismatch' ,
284- 'DataError' ) ;
285- }
286222
287223 if ( keyData . alg !== undefined && ( name === 'Ed25519' || name === 'Ed448' ) ) {
288- if ( keyData . alg !== name && keyData . alg !== 'EdDSA' ) {
224+ if ( keyData . alg !== name && keyData . alg !== 'EdDSA' )
289225 throw lazyDOMException (
290- 'JWK "alg" does not match the requested algorithm' ,
291- 'DataError' ) ;
292- }
226+ 'JWK "alg" does not match the requested algorithm' , 'DataError' ) ;
293227 }
294228
295- if ( ! isPublic && typeof keyData . x !== 'string' ) {
296- throw lazyDOMException ( 'Invalid JWK' , 'DataError' ) ;
297- }
298-
299- verifyAcceptableCfrgKeyUse (
300- name ,
301- isPublic ,
302- usagesSet ) ;
303-
304- try {
305- const publicKeyObject = createCFRGRawKey (
306- name ,
307- Buffer . from ( keyData . x , 'base64' ) ,
308- true ) ;
309-
310- if ( isPublic ) {
311- keyObject = publicKeyObject ;
312- } else {
313- keyObject = createCFRGRawKey (
314- name ,
315- Buffer . from ( keyData . d , 'base64' ) ,
316- false ) ;
229+ const isPublic = keyData . d === undefined ;
230+ verifyAcceptableCfrgKeyUse ( name , isPublic , usagesSet ) ;
231+ keyObject = importJwkKey ( isPublic , keyData ) ;
317232
318- if ( ! createPublicKey ( keyObject ) . equals ( publicKeyObject ) ) {
319- throw new ERR_CRYPTO_INVALID_JWK ( ) ;
320- }
321- }
322- } catch ( err ) {
323- throw lazyDOMException ( 'Invalid keyData' , { name : 'DataError' , cause : err } ) ;
233+ if ( ! isPublic ) {
234+ const publicKey = Buffer . from ( keyData . x , 'base64url' ) ;
235+ if ( ! Buffer . from ( keyObject [ kHandle ] . rawPublicKey ( ) ) . equals ( publicKey ) )
236+ throw lazyDOMException ( 'Invalid keyData' , 'DataError' ) ;
324237 }
325238 break ;
326239 }
327240 case 'raw' : {
328241 verifyAcceptableCfrgKeyUse ( name , true , usagesSet ) ;
329- keyObject = createCFRGRawKey ( name , keyData , true ) ;
242+ keyObject = importRawKey ( true , keyData , kKeyFormatRawPublic , name ) ;
330243 break ;
331244 }
332245 default :
@@ -340,7 +253,7 @@ function cfrgImportKey(
340253 return new InternalCryptoKey (
341254 keyObject ,
342255 { name } ,
343- usagesSet ,
256+ keyUsages ,
344257 extractable ) ;
345258}
346259
@@ -358,6 +271,7 @@ async function eddsaSignVerify(key, data, algorithm, signature) {
358271 undefined ,
359272 undefined ,
360273 undefined ,
274+ undefined ,
361275 data ,
362276 undefined ,
363277 undefined ,
0 commit comments