11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciif (!common.hasCrypto)
41cb0ef41Sopenharmony_ci  common.skip('missing crypto');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst { ECDH, createSign, getCurves } = require('crypto');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// A valid private key for the secp256k1 curve.
111cb0ef41Sopenharmony_ciconst cafebabeKey = 'cafebabe'.repeat(8);
121cb0ef41Sopenharmony_ci// Associated compressed and uncompressed public keys (points).
131cb0ef41Sopenharmony_ciconst cafebabePubPtComp =
141cb0ef41Sopenharmony_ci    '03672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3';
151cb0ef41Sopenharmony_ciconst cafebabePubPtUnComp =
161cb0ef41Sopenharmony_ci    '04672a31bfc59d3f04548ec9b7daeeba2f61814e8ccc40448045007f5479f693a3' +
171cb0ef41Sopenharmony_ci    '2e02c7f93d13dc2732b760ca377a5897b9dd41a1c1b29dc0442fdce6d0a04d1d';
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci// Invalid test: key argument is undefined.
201cb0ef41Sopenharmony_ciassert.throws(
211cb0ef41Sopenharmony_ci  () => ECDH.convertKey(),
221cb0ef41Sopenharmony_ci  {
231cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
241cb0ef41Sopenharmony_ci    name: 'TypeError',
251cb0ef41Sopenharmony_ci  });
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci// Invalid test: curve argument is undefined.
281cb0ef41Sopenharmony_ciassert.throws(
291cb0ef41Sopenharmony_ci  () => ECDH.convertKey(cafebabePubPtComp),
301cb0ef41Sopenharmony_ci  {
311cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
321cb0ef41Sopenharmony_ci    name: 'TypeError',
331cb0ef41Sopenharmony_ci  });
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci// Invalid test: curve argument is invalid.
361cb0ef41Sopenharmony_ciassert.throws(
371cb0ef41Sopenharmony_ci  () => ECDH.convertKey(cafebabePubPtComp, 'badcurve'),
381cb0ef41Sopenharmony_ci  {
391cb0ef41Sopenharmony_ci    name: 'TypeError',
401cb0ef41Sopenharmony_ci    message: 'Invalid EC curve name'
411cb0ef41Sopenharmony_ci  });
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciif (getCurves().includes('secp256k1')) {
441cb0ef41Sopenharmony_ci  // Invalid test: format argument is undefined.
451cb0ef41Sopenharmony_ci  assert.throws(
461cb0ef41Sopenharmony_ci    () => ECDH.convertKey(cafebabePubPtComp, 'secp256k1', 'hex', 'hex', 10),
471cb0ef41Sopenharmony_ci    {
481cb0ef41Sopenharmony_ci      code: 'ERR_CRYPTO_ECDH_INVALID_FORMAT',
491cb0ef41Sopenharmony_ci      name: 'TypeError',
501cb0ef41Sopenharmony_ci      message: 'Invalid ECDH format: 10'
511cb0ef41Sopenharmony_ci    });
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  // Point formats.
541cb0ef41Sopenharmony_ci  let uncompressed = ECDH.convertKey(cafebabePubPtComp,
551cb0ef41Sopenharmony_ci                                     'secp256k1',
561cb0ef41Sopenharmony_ci                                     'hex',
571cb0ef41Sopenharmony_ci                                     'buffer',
581cb0ef41Sopenharmony_ci                                     'uncompressed');
591cb0ef41Sopenharmony_ci  let compressed = ECDH.convertKey(cafebabePubPtComp,
601cb0ef41Sopenharmony_ci                                   'secp256k1',
611cb0ef41Sopenharmony_ci                                   'hex',
621cb0ef41Sopenharmony_ci                                   'buffer',
631cb0ef41Sopenharmony_ci                                   'compressed');
641cb0ef41Sopenharmony_ci  let hybrid = ECDH.convertKey(cafebabePubPtComp,
651cb0ef41Sopenharmony_ci                               'secp256k1',
661cb0ef41Sopenharmony_ci                               'hex',
671cb0ef41Sopenharmony_ci                               'buffer',
681cb0ef41Sopenharmony_ci                               'hybrid');
691cb0ef41Sopenharmony_ci  assert.strictEqual(uncompressed[0], 4);
701cb0ef41Sopenharmony_ci  let firstByte = compressed[0];
711cb0ef41Sopenharmony_ci  assert(firstByte === 2 || firstByte === 3);
721cb0ef41Sopenharmony_ci  firstByte = hybrid[0];
731cb0ef41Sopenharmony_ci  assert(firstByte === 6 || firstByte === 7);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  // Format conversion from hex to hex
761cb0ef41Sopenharmony_ci  uncompressed = ECDH.convertKey(cafebabePubPtComp,
771cb0ef41Sopenharmony_ci                                 'secp256k1',
781cb0ef41Sopenharmony_ci                                 'hex',
791cb0ef41Sopenharmony_ci                                 'hex',
801cb0ef41Sopenharmony_ci                                 'uncompressed');
811cb0ef41Sopenharmony_ci  compressed = ECDH.convertKey(cafebabePubPtComp,
821cb0ef41Sopenharmony_ci                               'secp256k1',
831cb0ef41Sopenharmony_ci                               'hex',
841cb0ef41Sopenharmony_ci                               'hex',
851cb0ef41Sopenharmony_ci                               'compressed');
861cb0ef41Sopenharmony_ci  hybrid = ECDH.convertKey(cafebabePubPtComp,
871cb0ef41Sopenharmony_ci                           'secp256k1',
881cb0ef41Sopenharmony_ci                           'hex',
891cb0ef41Sopenharmony_ci                           'hex',
901cb0ef41Sopenharmony_ci                           'hybrid');
911cb0ef41Sopenharmony_ci  assert.strictEqual(uncompressed, cafebabePubPtUnComp);
921cb0ef41Sopenharmony_ci  assert.strictEqual(compressed, cafebabePubPtComp);
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  // Compare to getPublicKey.
951cb0ef41Sopenharmony_ci  const ecdh1 = ECDH('secp256k1');
961cb0ef41Sopenharmony_ci  ecdh1.generateKeys();
971cb0ef41Sopenharmony_ci  ecdh1.setPrivateKey(cafebabeKey, 'hex');
981cb0ef41Sopenharmony_ci  assert.strictEqual(ecdh1.getPublicKey('hex', 'uncompressed'), uncompressed);
991cb0ef41Sopenharmony_ci  assert.strictEqual(ecdh1.getPublicKey('hex', 'compressed'), compressed);
1001cb0ef41Sopenharmony_ci  assert.strictEqual(ecdh1.getPublicKey('hex', 'hybrid'), hybrid);
1011cb0ef41Sopenharmony_ci}
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci// See https://github.com/nodejs/node/issues/26133, failed ConvertKey
1041cb0ef41Sopenharmony_ci// operations should not leave errors on OpenSSL's error stack because
1051cb0ef41Sopenharmony_ci// that's observable by subsequent operations.
1061cb0ef41Sopenharmony_ci{
1071cb0ef41Sopenharmony_ci  const privateKey =
1081cb0ef41Sopenharmony_ci    '-----BEGIN EC PRIVATE KEY-----\n' +
1091cb0ef41Sopenharmony_ci    'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
1101cb0ef41Sopenharmony_ci    'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
1111cb0ef41Sopenharmony_ci    'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
1121cb0ef41Sopenharmony_ci    '-----END EC PRIVATE KEY-----';
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  const sign = createSign('sha256').update('plaintext');
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  // TODO(bnoordhuis) This should really bubble up the specific OpenSSL error
1171cb0ef41Sopenharmony_ci  // rather than Node's generic error message.
1181cb0ef41Sopenharmony_ci  const badKey = 'f'.repeat(128);
1191cb0ef41Sopenharmony_ci  assert.throws(
1201cb0ef41Sopenharmony_ci    () => ECDH.convertKey(badKey, 'secp521r1', 'hex', 'hex', 'compressed'),
1211cb0ef41Sopenharmony_ci    /Failed to convert Buffer to EC_POINT/);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  // Next statement should not throw an exception.
1241cb0ef41Sopenharmony_ci  sign.sign(privateKey);
1251cb0ef41Sopenharmony_ci}
126