Skip to content

Commit ac400a7

Browse files
Qantas94HeavyMylesBorins
authored andcommitted
test: check curve algorithm is supported
parallel/test-crypto-dh.js assumes particular curve algorithms (e.g. Oakley-EC2N-3) are supported, though this may not necessarily be the case if Node.js was built with a system version of OpenSSL.
1 parent 47e7020 commit ac400a7

1 file changed

Lines changed: 138 additions & 127 deletions

File tree

‎test/parallel/test-crypto-dh.js‎

Lines changed: 138 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -161,146 +161,157 @@ const bad_dh = crypto.createDiffieHellman(p, 'hex');
161161
assert.strictEqual(bad_dh.verifyError,DH_NOT_SUITABLE_GENERATOR);
162162

163163

164-
// Test ECDH
165-
constecdh1=crypto.createECDH('prime256v1');
166-
constecdh2=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+
constavailableCurves=newSet(crypto.getCurves());
173165

174166
// Oakley curves do not clean up ERR stack, it was causing unexpected failure
175167
// 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-
letfirstByte=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-
},/^TypeError:Badformat:10$/);
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+
constecdh1=crypto.createECDH('prime256v1');
176+
constecdh2=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+
letfirstByte=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+
},/^TypeError:Badformat:10$/);
189194

190-
// ECDH should check that point is on curve
191-
constecdh3=crypto.createECDH('secp256k1');
192-
constkey3=ecdh3.generateKeys();
195+
// ECDH should check that point is on curve
196+
constecdh3=crypto.createECDH('secp256k1');
197+
constkey3=ecdh3.generateKeys();
193198

194-
assert.throws(()=>{
195-
ecdh2.computeSecret(key3,'latin1','buffer');
196-
},/^Error:FailedtotranslateBuffertoaEC_POINT$/);
199+
assert.throws(()=>{
200+
ecdh2.computeSecret(key3,'latin1','buffer');
201+
},/^Error:FailedtotranslateBuffertoaEC_POINT$/);
197202

198-
// ECDH should allow .setPrivateKey()/.setPublicKey()
199-
constecdh4=crypto.createECDH('prime256v1');
203+
// ECDH should allow .setPrivateKey()/.setPublicKey()
204+
constecdh4=crypto.createECDH('prime256v1');
200205

201-
ecdh4.setPrivateKey(ecdh1.getPrivateKey());
202-
ecdh4.setPublicKey(ecdh1.getPublicKey());
206+
ecdh4.setPrivateKey(ecdh1.getPrivateKey());
207+
ecdh4.setPublicKey(ecdh1.getPublicKey());
203208

204-
assert.throws(()=>{
205-
ecdh4.setPublicKey(ecdh3.getPublicKey());
206-
},/^Error:FailedtoconvertBuffertoEC_POINT$/);
209+
assert.throws(()=>{
210+
ecdh4.setPublicKey(ecdh3.getPublicKey());
211+
},/^Error:FailedtoconvertBuffertoEC_POINT$/);
207212

208-
// Verify that we can use ECDH without having to use newly generated keys.
209-
constecdh5=crypto.createECDH('secp256k1');
213+
// Verify that we can use ECDH without having to use newly generated keys.
214+
constecdh5=crypto.createECDH('secp256k1');
210215

211-
// Verify errors are thrown when retrieving keys from an uninitialized object.
212-
assert.throws(()=>{
213-
ecdh5.getPublicKey();
214-
},/^Error:FailedtogetECDHpublickey$/);
216+
// Verify errors are thrown when retrieving keys from an uninitialized object.
217+
assert.throws(()=>{
218+
ecdh5.getPublicKey();
219+
},/^Error:FailedtogetECDHpublickey$/);
215220

216-
assert.throws(()=>{
217-
ecdh5.getPrivateKey();
218-
},/^Error:FailedtogetECDHprivatekey$/);
219-
220-
// A valid private key for the secp256k1 curve.
221-
constcafebabeKey='cafebabe'.repeat(8);
222-
// Associated compressed and uncompressed public keys (points).
223-
constcafebabePubPtComp=
224-
'03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3';
225-
constcafebabePubPtUnComp=
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-
constpeerPubPtComp=
236-
'02c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae';
237-
constpeerPubPtUnComp=
238-
'04c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae'+
239-
'b651944a574a362082a77e3f2b5d9223eb54d7f2f76846522bf75f3bedb8178e';
240-
241-
constsharedSecret=
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-
},/^Error:Invalidkeypair$/);
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)=>{
278221
assert.throws(()=>{
279-
ecdh5.setPrivateKey(element,'hex');
280-
},/^Error:Privatekeyisnotvalidforspecifiedcurve.$/);
281-
// Verify object state did not change.
222+
ecdh5.getPrivateKey();
223+
},/^Error:FailedtogetECDHprivatekey$/);
224+
225+
// A valid private key for the secp256k1 curve.
226+
constcafebabeKey='cafebabe'.repeat(8);
227+
// Associated compressed and uncompressed public keys (points).
228+
constcafebabePubPtComp=
229+
'03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3';
230+
constcafebabePubPtUnComp=
231+
'04672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3'+
232+
'2e02c7f93d13dc2732b760ca377a5897b9dd41a1c1b29dc0442fdce6d0a04d1d';
233+
ecdh5.setPrivateKey(cafebabeKey,'hex');
282234
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-
constecdh6=crypto.createECDH('prime256v1');
288-
constinvalidKey=Buffer.alloc(65);
289-
invalidKey.fill('\0');
290-
ecdh6.generateKeys();
291-
assert.throws(()=>{
292-
ecdh6.computeSecret(invalidKey);
293-
},/^Error:FailedtotranslateBuffertoaEC_POINT$/);
294-
// Check that signing operations are not impacted by the above error.
295-
constecPrivateKey=
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+
constpeerPubPtComp=
243+
'02c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae';
244+
constpeerPubPtUnComp=
245+
'04c6b754b20826eb925e052ee2c25285b162b51fdca732bcf67e39d647fb6830ae'+
246+
'b651944a574a362082a77e3f2b5d9223eb54d7f2f76846522bf75f3bedb8178e';
247+
248+
constsharedSecret=
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+
},/^Error:Invalidkeypair$/);
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+
},/^Error:Privatekeyisnotvalidforspecifiedcurve.$/);
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+
constecdh6=crypto.createECDH('prime256v1');
298+
constinvalidKey=Buffer.alloc(65);
299+
invalidKey.fill('\0');
300+
ecdh6.generateKeys();
301+
assert.throws(()=>{
302+
ecdh6.computeSecret(invalidKey);
303+
},/^Error:FailedtotranslateBuffertoaEC_POINT$/);
304+
// Check that signing operations are not impacted by the above error.
305+
constecPrivateKey=
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+
}
304315

305316
// invalid test: curve argument is undefined
306317
assert.throws(()=>{

0 commit comments

Comments
 (0)