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