@@ -47,19 +47,23 @@ function testSignVerify(publicKey, privateKey) {
47
47
}
48
48
49
49
// Constructs a regular expression for a PEM-encoded key with the given label.
50
- function getRegExpForPEM ( label ) {
50
+ function getRegExpForPEM ( label , cipher ) {
51
51
const head = `\\-\\-\\-\\-\\-BEGIN ${ label } \\-\\-\\-\\-\\-` ;
52
+ const rfc1421Header = cipher == null ? '' :
53
+ `\nProc-Type: 4,ENCRYPTED\nDEK-Info: ${ cipher } ,[^\n]+\n` ;
52
54
const body = '([a-zA-Z0-9\\+/=]{64}\n)*[a-zA-Z0-9\\+/=]{1,64}' ;
53
55
const end = `\\-\\-\\-\\-\\-END ${ label } \\-\\-\\-\\-\\-` ;
54
- return new RegExp ( `^${ head } \n${ body } \n${ end } \n$` ) ;
56
+ return new RegExp ( `^${ head } ${ rfc1421Header } \n${ body } \n${ end } \n$` ) ;
55
57
}
56
58
57
59
const pkcs1PubExp = getRegExpForPEM ( 'RSA PUBLIC KEY' ) ;
58
60
const pkcs1PrivExp = getRegExpForPEM ( 'RSA PRIVATE KEY' ) ;
61
+ const pkcs1EncExp = ( cipher ) => getRegExpForPEM ( 'RSA PRIVATE KEY' , cipher ) ;
59
62
const spkiExp = getRegExpForPEM ( 'PUBLIC KEY' ) ;
60
63
const pkcs8Exp = getRegExpForPEM ( 'PRIVATE KEY' ) ;
61
64
const pkcs8EncExp = getRegExpForPEM ( 'ENCRYPTED PRIVATE KEY' ) ;
62
65
const sec1Exp = getRegExpForPEM ( 'EC PRIVATE KEY' ) ;
66
+ const sec1EncExp = ( cipher ) => getRegExpForPEM ( 'EC PRIVATE KEY' , cipher ) ;
63
67
64
68
// Since our own APIs only accept PEM, not DER, we need to convert DER to PEM
65
69
// for testing.
@@ -137,6 +141,42 @@ function convertDERToPEM(label, der) {
137
141
testEncryptDecrypt ( publicKey , privateKey ) ;
138
142
testSignVerify ( publicKey , privateKey ) ;
139
143
} ) ) ;
144
+
145
+ // Now do the same with an encrypted private key.
146
+ generateKeyPair ( 'rsa' , {
147
+ publicExponent : 0x10001 ,
148
+ modulusLength : 4096 ,
149
+ publicKeyEncoding : {
150
+ type : 'pkcs1' ,
151
+ format : 'der'
152
+ } ,
153
+ privateKeyEncoding : {
154
+ type : 'pkcs1' ,
155
+ format : 'pem' ,
156
+ cipher : 'aes-256-cbc' ,
157
+ passphrase : 'secret'
158
+ }
159
+ } , common . mustCall ( ( err , publicKeyDER , privateKey ) => {
160
+ assert . ifError ( err ) ;
161
+
162
+ // The public key is encoded as DER (which is binary) instead of PEM. We
163
+ // will still need to convert it to PEM for testing.
164
+ assert ( Buffer . isBuffer ( publicKeyDER ) ) ;
165
+ const publicKey = convertDERToPEM ( 'RSA PUBLIC KEY' , publicKeyDER ) ;
166
+ assertApproximateSize ( publicKey , 720 ) ;
167
+
168
+ assert . strictEqual ( typeof privateKey , 'string' ) ;
169
+ assert ( pkcs1EncExp ( 'AES-256-CBC' ) . test ( privateKey ) ) ;
170
+
171
+ // Since the private key is encrypted, signing shouldn't work anymore.
172
+ assert . throws ( ( ) => {
173
+ testSignVerify ( publicKey , privateKey ) ;
174
+ } , / b a d d e c r y p t | a s n 1 e n c o d i n g r o u t i n e s / ) ;
175
+
176
+ const key = { key : privateKey , passphrase : 'secret' } ;
177
+ testEncryptDecrypt ( publicKey , key ) ;
178
+ testSignVerify ( publicKey , key ) ;
179
+ } ) ) ;
140
180
}
141
181
142
182
{
@@ -203,6 +243,36 @@ function convertDERToPEM(label, der) {
203
243
204
244
testSignVerify ( publicKey , privateKey ) ;
205
245
} ) ) ;
246
+
247
+ // Do the same with an encrypted private key.
248
+ generateKeyPair ( 'ec' , {
249
+ namedCurve : 'prime256v1' ,
250
+ paramEncoding : 'named' ,
251
+ publicKeyEncoding : {
252
+ type : 'spki' ,
253
+ format : 'pem'
254
+ } ,
255
+ privateKeyEncoding : {
256
+ type : 'sec1' ,
257
+ format : 'pem' ,
258
+ cipher : 'aes-128-cbc' ,
259
+ passphrase : 'secret'
260
+ }
261
+ } , common . mustCall ( ( err , publicKey , privateKey ) => {
262
+ assert . ifError ( err ) ;
263
+
264
+ assert . strictEqual ( typeof publicKey , 'string' ) ;
265
+ assert ( spkiExp . test ( publicKey ) ) ;
266
+ assert . strictEqual ( typeof privateKey , 'string' ) ;
267
+ assert ( sec1EncExp ( 'AES-128-CBC' ) . test ( privateKey ) ) ;
268
+
269
+ // Since the private key is encrypted, signing shouldn't work anymore.
270
+ assert . throws ( ( ) => {
271
+ testSignVerify ( publicKey , privateKey ) ;
272
+ } , / b a d d e c r y p t | a s n 1 e n c o d i n g r o u t i n e s / ) ;
273
+
274
+ testSignVerify ( publicKey , { key : privateKey , passphrase : 'secret' } ) ;
275
+ } ) ) ;
206
276
}
207
277
208
278
{
@@ -640,7 +710,7 @@ function convertDERToPEM(label, der) {
640
710
} ) ;
641
711
}
642
712
643
- // Attempting to encrypt a non-PKCS#8 key.
713
+ // Attempting to encrypt a DER-encoded, non-PKCS#8 key.
644
714
for ( const type of [ 'pkcs1' , 'sec1' ] ) {
645
715
common . expectsError ( ( ) => {
646
716
generateKeyPairSync ( type === 'pkcs1' ? 'rsa' : 'ec' , {
@@ -649,7 +719,7 @@ function convertDERToPEM(label, der) {
649
719
publicKeyEncoding : { type : 'spki' , format : 'pem' } ,
650
720
privateKeyEncoding : {
651
721
type,
652
- format : 'pem ' ,
722
+ format : 'der ' ,
653
723
cipher : 'aes-128-cbc' ,
654
724
passphrase : 'hello'
655
725
}
0 commit comments