• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5
6const assert = require('assert');
7
8const { ECDH, createSign, getCurves } = require('crypto');
9
10// A valid private key for the secp256k1 curve.
11const cafebabeKey = 'cafebabe'.repeat(8);
12// Associated compressed and uncompressed public keys (points).
13const cafebabePubPtComp =
14    '03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3';
15const cafebabePubPtUnComp =
16    '04672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' +
17    '2e02c7f93d13dc2732b760ca377a5897b9dd41a1c1b29dc0442fdce6d0a04d1d';
18
19// Invalid test: key argument is undefined.
20assert.throws(
21  () => ECDH.convertKey(),
22  {
23    code: 'ERR_INVALID_ARG_TYPE',
24    name: 'TypeError',
25  });
26
27// Invalid test: curve argument is undefined.
28assert.throws(
29  () => ECDH.convertKey(cafebabePubPtComp),
30  {
31    code: 'ERR_INVALID_ARG_TYPE',
32    name: 'TypeError',
33  });
34
35// Invalid test: curve argument is invalid.
36assert.throws(
37  () => ECDH.convertKey(cafebabePubPtComp, 'badcurve'),
38  {
39    name: 'TypeError',
40    message: 'Invalid ECDH curve name'
41  });
42
43if (getCurves().includes('secp256k1')) {
44  // Invalid test: format argument is undefined.
45  assert.throws(
46    () => ECDH.convertKey(cafebabePubPtComp, 'secp256k1', 'hex', 'hex', 10),
47    {
48      code: 'ERR_CRYPTO_ECDH_INVALID_FORMAT',
49      name: 'TypeError',
50      message: 'Invalid ECDH format: 10'
51    });
52
53  // Point formats.
54  let uncompressed = ECDH.convertKey(cafebabePubPtComp,
55                                     'secp256k1',
56                                     'hex',
57                                     'buffer',
58                                     'uncompressed');
59  let compressed = ECDH.convertKey(cafebabePubPtComp,
60                                   'secp256k1',
61                                   'hex',
62                                   'buffer',
63                                   'compressed');
64  let hybrid = ECDH.convertKey(cafebabePubPtComp,
65                               'secp256k1',
66                               'hex',
67                               'buffer',
68                               'hybrid');
69  assert.strictEqual(uncompressed[0], 4);
70  let firstByte = compressed[0];
71  assert(firstByte === 2 || firstByte === 3);
72  firstByte = hybrid[0];
73  assert(firstByte === 6 || firstByte === 7);
74
75  // Format conversion from hex to hex
76  uncompressed = ECDH.convertKey(cafebabePubPtComp,
77                                 'secp256k1',
78                                 'hex',
79                                 'hex',
80                                 'uncompressed');
81  compressed = ECDH.convertKey(cafebabePubPtComp,
82                               'secp256k1',
83                               'hex',
84                               'hex',
85                               'compressed');
86  hybrid = ECDH.convertKey(cafebabePubPtComp,
87                           'secp256k1',
88                           'hex',
89                           'hex',
90                           'hybrid');
91  assert.strictEqual(uncompressed, cafebabePubPtUnComp);
92  assert.strictEqual(compressed, cafebabePubPtComp);
93
94  // Compare to getPublicKey.
95  const ecdh1 = ECDH('secp256k1');
96  ecdh1.generateKeys();
97  ecdh1.setPrivateKey(cafebabeKey, 'hex');
98  assert.strictEqual(ecdh1.getPublicKey('hex', 'uncompressed'), uncompressed);
99  assert.strictEqual(ecdh1.getPublicKey('hex', 'compressed'), compressed);
100  assert.strictEqual(ecdh1.getPublicKey('hex', 'hybrid'), hybrid);
101}
102
103// See https://github.com/nodejs/node/issues/26133, failed ConvertKey
104// operations should not leave errors on OpenSSL's error stack because
105// that's observable by subsequent operations.
106{
107  const privateKey =
108    '-----BEGIN EC PRIVATE KEY-----\n' +
109    'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
110    'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
111    'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
112    '-----END EC PRIVATE KEY-----';
113
114  const sign = createSign('sha256').update('plaintext');
115
116  // TODO(bnoordhuis) This should really bubble up the specific OpenSSL error
117  // rather than Node's generic error message.
118  const badKey = 'f'.repeat(128);
119  assert.throws(
120    () => ECDH.convertKey(badKey, 'secp256k1', 'hex', 'hex', 'compressed'),
121    /Failed to convert Buffer to EC_POINT/);
122
123  // Next statement should not throw an exception.
124  sign.sign(privateKey);
125}
126