2
2
3
3
const {
4
4
SafeSet,
5
+ Uint8Array,
5
6
} = primordials ;
6
7
7
8
const { Buffer } = require ( 'buffer' ) ;
@@ -14,6 +15,10 @@ const {
14
15
kKeyTypePublic,
15
16
kSignJobModeSign,
16
17
kSignJobModeVerify,
18
+ kKeyFormatDER,
19
+ kWebCryptoKeyFormatRaw,
20
+ kWebCryptoKeyFormatPKCS8,
21
+ kWebCryptoKeyFormatSPKI,
17
22
} = internalBinding ( 'crypto' ) ;
18
23
19
24
const {
@@ -44,6 +49,7 @@ const {
44
49
InternalCryptoKey,
45
50
PrivateKeyObject,
46
51
PublicKeyObject,
52
+ createPrivateKey,
47
53
createPublicKey,
48
54
} = require ( 'internal/crypto/keys' ) ;
49
55
@@ -106,15 +112,47 @@ async function mlDsaGenerateKey(algorithm, extractable, keyUsages) {
106
112
return { __proto__ : null , privateKey, publicKey } ;
107
113
}
108
114
109
- function mlDsaExportKey ( key ) {
115
+ function mlDsaExportKey ( key , format ) {
110
116
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
+ }
115
123
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
+ }
118
156
} catch ( err ) {
119
157
throw lazyDOMException (
120
158
'The operation failed for an operation-specific reason' ,
@@ -138,6 +176,34 @@ function mlDsaImportKey(
138
176
keyObject = keyData ;
139
177
break ;
140
178
}
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
+ }
141
207
case 'jwk' : {
142
208
if ( ! keyData . kty )
143
209
throw lazyDOMException ( 'Invalid keyData' , 'DataError' ) ;
0 commit comments