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