@@ -161,146 +161,157 @@ const bad_dh = crypto.createDiffieHellman(p, 'hex');
161
161
assert . strictEqual ( bad_dh . verifyError , DH_NOT_SUITABLE_GENERATOR ) ;
162
162
163
163
164
- // Test ECDH
165
- const ecdh1 = crypto . createECDH ( 'prime256v1' ) ;
166
- const ecdh2 = crypto . createECDH ( 'prime256v1' ) ;
167
- key1 = ecdh1 . generateKeys ( ) ;
168
- key2 = ecdh2 . generateKeys ( 'hex' ) ;
169
- secret1 = ecdh1 . computeSecret ( key2 , 'hex' , 'base64' ) ;
170
- secret2 = ecdh2 . computeSecret ( key1 , 'latin1' , 'buffer' ) ;
171
-
172
- assert . strictEqual ( secret1 , secret2 . toString ( 'base64' ) ) ;
164
+ const availableCurves = new Set ( crypto . getCurves ( ) ) ;
173
165
174
166
// Oakley curves do not clean up ERR stack, it was causing unexpected failure
175
167
// when accessing other OpenSSL APIs afterwards.
176
- crypto . createECDH ( 'Oakley-EC2N-3' ) ;
177
- crypto . createHash ( 'sha256' ) ;
178
-
179
- // Point formats
180
- assert . strictEqual ( ecdh1 . getPublicKey ( 'buffer' , 'uncompressed' ) [ 0 ] , 4 ) ;
181
- let firstByte = ecdh1 . getPublicKey ( 'buffer' , 'compressed' ) [ 0 ] ;
182
- assert ( firstByte === 2 || firstByte === 3 ) ;
183
- firstByte = ecdh1 . getPublicKey ( 'buffer' , 'hybrid' ) [ 0 ] ;
184
- assert ( firstByte === 6 || firstByte === 7 ) ;
185
- // format value should be string
186
- assert . throws ( ( ) => {
187
- ecdh1 . getPublicKey ( 'buffer' , 10 ) ;
188
- } , / ^ T y p e E r r o r : B a d f o r m a t : 1 0 $ / ) ;
168
+ if ( availableCurves . has ( 'Oakley-EC2N-3' ) ) {
169
+ crypto . createECDH ( 'Oakley-EC2N-3' ) ;
170
+ crypto . createHash ( 'sha256' ) ;
171
+ }
172
+
173
+ // Test ECDH
174
+ if ( availableCurves . has ( 'prime256v1' ) && availableCurves . has ( 'secp256k1' ) ) {
175
+ const ecdh1 = crypto . createECDH ( 'prime256v1' ) ;
176
+ const ecdh2 = crypto . createECDH ( 'prime256v1' ) ;
177
+ key1 = ecdh1 . generateKeys ( ) ;
178
+ key2 = ecdh2 . generateKeys ( 'hex' ) ;
179
+ secret1 = ecdh1 . computeSecret ( key2 , 'hex' , 'base64' ) ;
180
+ secret2 = ecdh2 . computeSecret ( key1 , 'latin1' , 'buffer' ) ;
181
+
182
+ assert . strictEqual ( secret1 , secret2 . toString ( 'base64' ) ) ;
183
+
184
+ // Point formats
185
+ assert . strictEqual ( ecdh1 . getPublicKey ( 'buffer' , 'uncompressed' ) [ 0 ] , 4 ) ;
186
+ let firstByte = ecdh1 . getPublicKey ( 'buffer' , 'compressed' ) [ 0 ] ;
187
+ assert ( firstByte === 2 || firstByte === 3 ) ;
188
+ firstByte = ecdh1 . getPublicKey ( 'buffer' , 'hybrid' ) [ 0 ] ;
189
+ assert ( firstByte === 6 || firstByte === 7 ) ;
190
+ // format value should be string
191
+ assert . throws ( ( ) => {
192
+ ecdh1 . getPublicKey ( 'buffer' , 10 ) ;
193
+ } , / ^ T y p e E r r o r : B a d f o r m a t : 1 0 $ / ) ;
189
194
190
- // ECDH should check that point is on curve
191
- const ecdh3 = crypto . createECDH ( 'secp256k1' ) ;
192
- const key3 = ecdh3 . generateKeys ( ) ;
195
+ // ECDH should check that point is on curve
196
+ const ecdh3 = crypto . createECDH ( 'secp256k1' ) ;
197
+ const key3 = ecdh3 . generateKeys ( ) ;
193
198
194
- assert . throws ( ( ) => {
195
- ecdh2 . computeSecret ( key3 , 'latin1' , 'buffer' ) ;
196
- } , / ^ E r r o r : F a i l e d t o t r a n s l a t e B u f f e r t o a E C _ P O I N T $ / ) ;
199
+ assert . throws ( ( ) => {
200
+ ecdh2 . computeSecret ( key3 , 'latin1' , 'buffer' ) ;
201
+ } , / ^ E r r o r : F a i l e d t o t r a n s l a t e B u f f e r t o a E C _ P O I N T $ / ) ;
197
202
198
- // ECDH should allow .setPrivateKey()/.setPublicKey()
199
- const ecdh4 = crypto . createECDH ( 'prime256v1' ) ;
203
+ // ECDH should allow .setPrivateKey()/.setPublicKey()
204
+ const ecdh4 = crypto . createECDH ( 'prime256v1' ) ;
200
205
201
- ecdh4 . setPrivateKey ( ecdh1 . getPrivateKey ( ) ) ;
202
- ecdh4 . setPublicKey ( ecdh1 . getPublicKey ( ) ) ;
206
+ ecdh4 . setPrivateKey ( ecdh1 . getPrivateKey ( ) ) ;
207
+ ecdh4 . setPublicKey ( ecdh1 . getPublicKey ( ) ) ;
203
208
204
- assert . throws ( ( ) => {
205
- ecdh4 . setPublicKey ( ecdh3 . getPublicKey ( ) ) ;
206
- } , / ^ E r r o r : F a i l e d t o c o n v e r t B u f f e r t o E C _ P O I N T $ / ) ;
209
+ assert . throws ( ( ) => {
210
+ ecdh4 . setPublicKey ( ecdh3 . getPublicKey ( ) ) ;
211
+ } , / ^ E r r o r : F a i l e d t o c o n v e r t B u f f e r t o E C _ P O I N T $ / ) ;
207
212
208
- // Verify that we can use ECDH without having to use newly generated keys.
209
- const ecdh5 = crypto . createECDH ( 'secp256k1' ) ;
213
+ // Verify that we can use ECDH without having to use newly generated keys.
214
+ const ecdh5 = crypto . createECDH ( 'secp256k1' ) ;
210
215
211
- // Verify errors are thrown when retrieving keys from an uninitialized object.
212
- assert . throws ( ( ) => {
213
- ecdh5 . getPublicKey ( ) ;
214
- } , / ^ E r r o r : F a i l e d t o g e t E C D H p u b l i c k e y $ / ) ;
216
+ // Verify errors are thrown when retrieving keys from an uninitialized object.
217
+ assert . throws ( ( ) => {
218
+ ecdh5 . getPublicKey ( ) ;
219
+ } , / ^ E r r o r : F a i l e d t o g e t E C D H p u b l i c k e y $ / ) ;
215
220
216
- assert . throws ( ( ) => {
217
- ecdh5 . getPrivateKey ( ) ;
218
- } , / ^ E r r o r : F a i l e d t o g e t E C D H p r i v a t e k e y $ / ) ;
219
-
220
- // A valid private key for the secp256k1 curve.
221
- const cafebabeKey = 'cafebabe' . repeat ( 8 ) ;
222
- // Associated compressed and uncompressed public keys (points).
223
- const cafebabePubPtComp =
224
- '03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' ;
225
- const cafebabePubPtUnComp =
226
- '04672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' +
227
- '2e02c7f93d13dc2732b760ca377a5897b9dd41a1c1b29dc0442fdce6d0a04d1d' ;
228
- ecdh5 . setPrivateKey ( cafebabeKey , 'hex' ) ;
229
- assert . strictEqual ( ecdh5 . getPrivateKey ( 'hex' ) , cafebabeKey ) ;
230
- // Show that the public point (key) is generated while setting the private key.
231
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
232
-
233
- // Compressed and uncompressed public points/keys for other party's private key
234
- // 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
235
- const peerPubPtComp =
236
- '02c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae' ;
237
- const peerPubPtUnComp =
238
- '04c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae' +
239
- 'b651944a574a362082a77e3f2b5d9223eb54d7f2f76846522bf75f3bedb8178e' ;
240
-
241
- const sharedSecret =
242
- '1da220b5329bbe8bfd19ceef5a5898593f411a6f12ea40f2a8eead9a5cf59970' ;
243
-
244
- assert . strictEqual ( ecdh5 . computeSecret ( peerPubPtComp , 'hex' , 'hex' ) ,
245
- sharedSecret ) ;
246
- assert . strictEqual ( ecdh5 . computeSecret ( peerPubPtUnComp , 'hex' , 'hex' ) ,
247
- sharedSecret ) ;
248
-
249
- // Verify that we still have the same key pair as before the computation.
250
- assert . strictEqual ( ecdh5 . getPrivateKey ( 'hex' ) , cafebabeKey ) ;
251
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
252
-
253
- // Verify setting and getting compressed and non-compressed serializations.
254
- ecdh5 . setPublicKey ( cafebabePubPtComp , 'hex' ) ;
255
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
256
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' , 'compressed' ) , cafebabePubPtComp ) ;
257
- ecdh5 . setPublicKey ( cafebabePubPtUnComp , 'hex' ) ;
258
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
259
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' , 'compressed' ) , cafebabePubPtComp ) ;
260
-
261
- // Show why allowing the public key to be set on this type does not make sense.
262
- ecdh5 . setPublicKey ( peerPubPtComp , 'hex' ) ;
263
- assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , peerPubPtUnComp ) ;
264
- assert . throws ( ( ) => {
265
- // Error because the public key does not match the private key anymore.
266
- ecdh5 . computeSecret ( peerPubPtComp , 'hex' , 'hex' ) ;
267
- } , / ^ E r r o r : I n v a l i d k e y p a i r $ / ) ;
268
-
269
- // Set to a valid key to show that later attempts to set an invalid key are
270
- // rejected.
271
- ecdh5 . setPrivateKey ( cafebabeKey , 'hex' ) ;
272
-
273
- [ // Some invalid private keys for the secp256k1 curve.
274
- '0000000000000000000000000000000000000000000000000000000000000000' ,
275
- 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141' ,
276
- 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ,
277
- ] . forEach ( ( element ) => {
278
221
assert . throws ( ( ) => {
279
- ecdh5 . setPrivateKey ( element , 'hex' ) ;
280
- } , / ^ E r r o r : P r i v a t e k e y i s n o t v a l i d f o r s p e c i f i e d c u r v e .$ / ) ;
281
- // Verify object state did not change.
222
+ ecdh5 . getPrivateKey ( ) ;
223
+ } , / ^ E r r o r : F a i l e d t o g e t E C D H p r i v a t e k e y $ / ) ;
224
+
225
+ // A valid private key for the secp256k1 curve.
226
+ const cafebabeKey = 'cafebabe' . repeat ( 8 ) ;
227
+ // Associated compressed and uncompressed public keys (points).
228
+ const cafebabePubPtComp =
229
+ '03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' ;
230
+ const cafebabePubPtUnComp =
231
+ '04672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' +
232
+ '2e02c7f93d13dc2732b760ca377a5897b9dd41a1c1b29dc0442fdce6d0a04d1d' ;
233
+ ecdh5 . setPrivateKey ( cafebabeKey , 'hex' ) ;
282
234
assert . strictEqual ( ecdh5 . getPrivateKey ( 'hex' ) , cafebabeKey ) ;
283
- } ) ;
284
-
285
- // Use of invalid keys was not cleaning up ERR stack, and was causing
286
- // unexpected failure in subsequent signing operations.
287
- const ecdh6 = crypto . createECDH ( 'prime256v1' ) ;
288
- const invalidKey = Buffer . alloc ( 65 ) ;
289
- invalidKey . fill ( '\0' ) ;
290
- ecdh6 . generateKeys ( ) ;
291
- assert . throws ( ( ) => {
292
- ecdh6 . computeSecret ( invalidKey ) ;
293
- } , / ^ E r r o r : F a i l e d t o t r a n s l a t e B u f f e r t o a E C _ P O I N T $ / ) ;
294
- // Check that signing operations are not impacted by the above error.
295
- const ecPrivateKey =
296
- '-----BEGIN EC PRIVATE KEY-----\n' +
297
- 'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
298
- 'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
299
- 'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
300
- '-----END EC PRIVATE KEY-----' ;
301
- assert . doesNotThrow ( ( ) => {
302
- crypto . createSign ( 'SHA256' ) . sign ( ecPrivateKey ) ;
303
- } ) ;
235
+ // Show that the public point (key) is generated while setting the
236
+ // private key.
237
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
238
+
239
+ // Compressed and uncompressed public points/keys for other party's
240
+ // private key.
241
+ // 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
242
+ const peerPubPtComp =
243
+ '02c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae' ;
244
+ const peerPubPtUnComp =
245
+ '04c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae' +
246
+ 'b651944a574a362082a77e3f2b5d9223eb54d7f2f76846522bf75f3bedb8178e' ;
247
+
248
+ const sharedSecret =
249
+ '1da220b5329bbe8bfd19ceef5a5898593f411a6f12ea40f2a8eead9a5cf59970' ;
250
+
251
+ assert . strictEqual ( ecdh5 . computeSecret ( peerPubPtComp , 'hex' , 'hex' ) ,
252
+ sharedSecret ) ;
253
+ assert . strictEqual ( ecdh5 . computeSecret ( peerPubPtUnComp , 'hex' , 'hex' ) ,
254
+ sharedSecret ) ;
255
+
256
+ // Verify that we still have the same key pair as before the computation.
257
+ assert . strictEqual ( ecdh5 . getPrivateKey ( 'hex' ) , cafebabeKey ) ;
258
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
259
+
260
+ // Verify setting and getting compressed and non-compressed serializations.
261
+ ecdh5 . setPublicKey ( cafebabePubPtComp , 'hex' ) ;
262
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
263
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' , 'compressed' ) ,
264
+ cafebabePubPtComp ) ;
265
+ ecdh5 . setPublicKey ( cafebabePubPtUnComp , 'hex' ) ;
266
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , cafebabePubPtUnComp ) ;
267
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' , 'compressed' ) ,
268
+ cafebabePubPtComp ) ;
269
+
270
+ // Show why allowing the public key to be set on this type
271
+ // does not make sense.
272
+ ecdh5 . setPublicKey ( peerPubPtComp , 'hex' ) ;
273
+ assert . strictEqual ( ecdh5 . getPublicKey ( 'hex' ) , peerPubPtUnComp ) ;
274
+ assert . throws ( ( ) => {
275
+ // Error because the public key does not match the private key anymore.
276
+ ecdh5 . computeSecret ( peerPubPtComp , 'hex' , 'hex' ) ;
277
+ } , / ^ E r r o r : I n v a l i d k e y p a i r $ / ) ;
278
+
279
+ // Set to a valid key to show that later attempts to set an invalid key are
280
+ // rejected.
281
+ ecdh5 . setPrivateKey ( cafebabeKey , 'hex' ) ;
282
+
283
+ [ // Some invalid private keys for the secp256k1 curve.
284
+ '0000000000000000000000000000000000000000000000000000000000000000' ,
285
+ 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141' ,
286
+ 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ,
287
+ ] . forEach ( ( element ) => {
288
+ assert . throws ( ( ) => {
289
+ ecdh5 . setPrivateKey ( element , 'hex' ) ;
290
+ } , / ^ E r r o r : P r i v a t e k e y i s n o t v a l i d f o r s p e c i f i e d c u r v e .$ / ) ;
291
+ // Verify object state did not change.
292
+ assert . strictEqual ( ecdh5 . getPrivateKey ( 'hex' ) , cafebabeKey ) ;
293
+ } ) ;
294
+
295
+ // Use of invalid keys was not cleaning up ERR stack, and was causing
296
+ // unexpected failure in subsequent signing operations.
297
+ const ecdh6 = crypto . createECDH ( 'prime256v1' ) ;
298
+ const invalidKey = Buffer . alloc ( 65 ) ;
299
+ invalidKey . fill ( '\0' ) ;
300
+ ecdh6 . generateKeys ( ) ;
301
+ assert . throws ( ( ) => {
302
+ ecdh6 . computeSecret ( invalidKey ) ;
303
+ } , / ^ E r r o r : F a i l e d t o t r a n s l a t e B u f f e r t o a E C _ P O I N T $ / ) ;
304
+ // Check that signing operations are not impacted by the above error.
305
+ const ecPrivateKey =
306
+ '-----BEGIN EC PRIVATE KEY-----\n' +
307
+ 'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
308
+ 'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
309
+ 'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
310
+ '-----END EC PRIVATE KEY-----' ;
311
+ assert . doesNotThrow ( ( ) => {
312
+ crypto . createSign ( 'SHA256' ) . sign ( ecPrivateKey ) ;
313
+ } ) ;
314
+ }
304
315
305
316
// invalid test: curve argument is undefined
306
317
assert . throws ( ( ) => {
0 commit comments