summaryrefslogtreecommitdiff
path: root/test/parallel/test-crypto-ecdh-convert-key.js
blob: 52d0fc2b7f0c74775377b55b8443c32dbae62202 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
'use strict';
const common = require('../common');
if (!common.hasCrypto)
  common.skip('missing crypto');

const assert = require('assert');

const { ECDH, createSign, getCurves } = require('crypto');

// A valid private key for the secp256k1 curve.
const cafebabeKey = 'cafebabe'.repeat(8);
// Associated compressed and uncompressed public keys (points).
const cafebabePubPtComp =
    '03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3';
const cafebabePubPtUnComp =
    '04672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' +
    '2e02c7f93d13dc2732b760ca377a5897b9dd41a1c1b29dc0442fdce6d0a04d1d';

// Invalid test: key argument is undefined.
common.expectsError(
  () => ECDH.convertKey(),
  {
    code: 'ERR_INVALID_ARG_TYPE',
    type: TypeError,
  });

// Invalid test: curve argument is undefined.
common.expectsError(
  () => ECDH.convertKey(cafebabePubPtComp),
  {
    code: 'ERR_INVALID_ARG_TYPE',
    type: TypeError,
  });

// Invalid test: curve argument is invalid.
common.expectsError(
  () => ECDH.convertKey(cafebabePubPtComp, 'badcurve'),
  {
    type: TypeError,
    message: 'Invalid ECDH curve name'
  });

if (getCurves().includes('secp256k1')) {
  // Invalid test: format argument is undefined.
  common.expectsError(
    () => ECDH.convertKey(cafebabePubPtComp, 'secp256k1', 'hex', 'hex', 10),
    {
      code: 'ERR_CRYPTO_ECDH_INVALID_FORMAT',
      type: TypeError,
      message: 'Invalid ECDH format: 10'
    });

  // Point formats.
  let uncompressed = ECDH.convertKey(cafebabePubPtComp,
                                     'secp256k1',
                                     'hex',
                                     'buffer',
                                     'uncompressed');
  let compressed = ECDH.convertKey(cafebabePubPtComp,
                                   'secp256k1',
                                   'hex',
                                   'buffer',
                                   'compressed');
  let hybrid = ECDH.convertKey(cafebabePubPtComp,
                               'secp256k1',
                               'hex',
                               'buffer',
                               'hybrid');
  assert.strictEqual(uncompressed[0], 4);
  let firstByte = compressed[0];
  assert(firstByte === 2 || firstByte === 3);
  firstByte = hybrid[0];
  assert(firstByte === 6 || firstByte === 7);

  // Format conversion from hex to hex
  uncompressed = ECDH.convertKey(cafebabePubPtComp,
                                 'secp256k1',
                                 'hex',
                                 'hex',
                                 'uncompressed');
  compressed = ECDH.convertKey(cafebabePubPtComp,
                               'secp256k1',
                               'hex',
                               'hex',
                               'compressed');
  hybrid = ECDH.convertKey(cafebabePubPtComp,
                           'secp256k1',
                           'hex',
                           'hex',
                           'hybrid');
  assert.strictEqual(uncompressed, cafebabePubPtUnComp);
  assert.strictEqual(compressed, cafebabePubPtComp);

  // Compare to getPublicKey.
  const ecdh1 = ECDH('secp256k1');
  ecdh1.generateKeys();
  ecdh1.setPrivateKey(cafebabeKey, 'hex');
  assert.strictEqual(ecdh1.getPublicKey('hex', 'uncompressed'), uncompressed);
  assert.strictEqual(ecdh1.getPublicKey('hex', 'compressed'), compressed);
  assert.strictEqual(ecdh1.getPublicKey('hex', 'hybrid'), hybrid);
}

// See https://github.com/nodejs/node/issues/26133, failed ConvertKey
// operations should not leave errors on OpenSSL's error stack because
// that's observable by subsequent operations.
{
  const privateKey =
    '-----BEGIN EC PRIVATE KEY-----\n' +
    'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
    'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
    'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
    '-----END EC PRIVATE KEY-----';

  const sign = createSign('sha256').update('plaintext');

  // TODO(bnoordhuis) This should really bubble up the specific OpenSSL error
  // rather than Node's generic error message.
  const badKey = 'f'.repeat(128);
  assert.throws(
    () => ECDH.convertKey(badKey, 'secp256k1', 'hex', 'hex', 'compressed'),
    /Failed to convert Buffer to EC_POINT/);

  // Next statement should not throw an exception.
  sign.sign(privateKey);
}