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