22
33const {
44 SafeSet,
5+ Uint8Array,
56} = primordials ;
67
78const { Buffer } = require ( 'buffer' ) ;
@@ -14,6 +15,10 @@ const {
1415 kKeyTypePublic,
1516 kSignJobModeSign,
1617 kSignJobModeVerify,
18+ kKeyFormatDER,
19+ kWebCryptoKeyFormatRaw,
20+ kWebCryptoKeyFormatPKCS8,
21+ kWebCryptoKeyFormatSPKI,
1722} = internalBinding ( 'crypto' ) ;
1823
1924const {
@@ -44,6 +49,7 @@ const {
4449 InternalCryptoKey,
4550 PrivateKeyObject,
4651 PublicKeyObject,
52+ createPrivateKey,
4753 createPublicKey,
4854} = require ( 'internal/crypto/keys' ) ;
4955
@@ -106,15 +112,47 @@ async function mlDsaGenerateKey(algorithm, extractable, keyUsages) {
106112 return { __proto__ : null , privateKey, publicKey } ;
107113}
108114
109- function mlDsaExportKey ( key ) {
115+ function mlDsaExportKey ( key , format ) {
110116 try {
111- if ( key . type === 'private' ) {
112- const { priv } = key [ kKeyObject ] [ kHandle ] . exportJwk ( { } , false ) ;
113- return Buffer . alloc ( 32 , priv , 'base64url' ) . buffer ;
114- }
117+ switch ( format ) {
118+ case kWebCryptoKeyFormatRaw : {
119+ if ( key . type === 'private' ) {
120+ const { priv } = key [ kKeyObject ] [ kHandle ] . exportJwk ( { } , false ) ;
121+ return Buffer . alloc ( 32 , priv , 'base64url' ) . buffer ;
122+ }
115123
116- const { pub } = key [ kKeyObject ] [ kHandle ] . exportJwk ( { } , false ) ;
117- return Buffer . alloc ( Buffer . byteLength ( pub , 'base64url' ) , pub , 'base64url' ) . buffer ;
124+ const { pub } = key [ kKeyObject ] [ kHandle ] . exportJwk ( { } , false ) ;
125+ return Buffer . alloc ( Buffer . byteLength ( pub , 'base64url' ) , pub , 'base64url' ) . buffer ;
126+ }
127+ case kWebCryptoKeyFormatSPKI : {
128+ return key [ kKeyObject ] [ kHandle ] . export ( kKeyFormatDER , kWebCryptoKeyFormatSPKI ) . buffer ;
129+ }
130+ case kWebCryptoKeyFormatPKCS8 : {
131+ const { priv } = key [ kKeyObject ] [ kHandle ] . exportJwk ( { } , false ) ;
132+ const seed = Buffer . alloc ( 32 , priv , 'base64url' ) ;
133+ const buffer = new Uint8Array ( 54 ) ;
134+ buffer . set ( [
135+ 0x30 , 0x34 , 0x02 , 0x01 , 0x00 , 0x30 , 0x0B , 0x06 ,
136+ 0x09 , 0x60 , 0x86 , 0x48 , 0x01 , 0x65 , 0x03 , 0x04 ,
137+ 0x03 , 0x00 , 0x04 , 0x22 , 0x80 , 0x20 ,
138+ ] , 0 ) ;
139+ switch ( key . algorithm . name ) {
140+ case 'ML-DSA-44' :
141+ buffer . set ( [ 0x11 ] , 17 ) ;
142+ break ;
143+ case 'ML-DSA-65' :
144+ buffer . set ( [ 0x12 ] , 17 ) ;
145+ break ;
146+ case 'ML-DSA-87' :
147+ buffer . set ( [ 0x13 ] , 17 ) ;
148+ break ;
149+ }
150+ buffer . set ( seed , 22 ) ;
151+ return buffer . buffer ;
152+ }
153+ default :
154+ return undefined ;
155+ }
118156 } catch ( err ) {
119157 throw lazyDOMException (
120158 'The operation failed for an operation-specific reason' ,
@@ -138,6 +176,34 @@ function mlDsaImportKey(
138176 keyObject = keyData ;
139177 break ;
140178 }
179+ case 'spki' : {
180+ verifyAcceptableMlDsaKeyUse ( name , true , usagesSet ) ;
181+ try {
182+ keyObject = createPublicKey ( {
183+ key : keyData ,
184+ format : 'der' ,
185+ type : 'spki' ,
186+ } ) ;
187+ } catch ( err ) {
188+ throw lazyDOMException (
189+ 'Invalid keyData' , { name : 'DataError' , cause : err } ) ;
190+ }
191+ break ;
192+ }
193+ case 'pkcs8' : {
194+ verifyAcceptableMlDsaKeyUse ( name , false , usagesSet ) ;
195+ try {
196+ keyObject = createPrivateKey ( {
197+ key : keyData ,
198+ format : 'der' ,
199+ type : 'pkcs8' ,
200+ } ) ;
201+ } catch ( err ) {
202+ throw lazyDOMException (
203+ 'Invalid keyData' , { name : 'DataError' , cause : err } ) ;
204+ }
205+ break ;
206+ }
141207 case 'jwk' : {
142208 if ( ! keyData . kty )
143209 throw lazyDOMException ( 'Invalid keyData' , 'DataError' ) ;
0 commit comments