1'use strict'; 2const common = require('../common'); 3if (!common.hasCrypto) 4 common.skip('missing crypto'); 5 6const assert = require('assert'); 7const crypto = require('crypto'); 8 9assert.throws(() => crypto.diffieHellman(), { 10 name: 'TypeError', 11 code: 'ERR_INVALID_ARG_TYPE', 12 message: 'The "options" argument must be of type object. Received undefined' 13}); 14 15assert.throws(() => crypto.diffieHellman(null), { 16 name: 'TypeError', 17 code: 'ERR_INVALID_ARG_TYPE', 18 message: 'The "options" argument must be of type object. Received null' 19}); 20 21assert.throws(() => crypto.diffieHellman([]), { 22 name: 'TypeError', 23 code: 'ERR_INVALID_ARG_TYPE', 24 message: 25 'The "options" argument must be of type object. ' + 26 'Received an instance of Array', 27}); 28 29function test({ publicKey: alicePublicKey, privateKey: alicePrivateKey }, 30 { publicKey: bobPublicKey, privateKey: bobPrivateKey }, 31 expectedValue) { 32 const buf1 = crypto.diffieHellman({ 33 privateKey: alicePrivateKey, 34 publicKey: bobPublicKey 35 }); 36 const buf2 = crypto.diffieHellman({ 37 privateKey: bobPrivateKey, 38 publicKey: alicePublicKey 39 }); 40 assert.deepStrictEqual(buf1, buf2); 41 42 if (expectedValue !== undefined) 43 assert.deepStrictEqual(buf1, expectedValue); 44} 45 46const alicePrivateKey = crypto.createPrivateKey({ 47 key: '-----BEGIN PRIVATE KEY-----\n' + 48 'MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n' + 49 'gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n' + 50 'bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n' + 51 '7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n' + 52 'cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwEh82IAVnYNf0Kjb\n' + 53 'qYSImDFyg9sH6CJ0GzRK05e6hM3dOSClFYi4kbA7Pr7zyfdn2SH6wSlNS14Jyrtt\n' + 54 'HePrRSeYl1T+tk0AfrvaLmyM56F+9B3jwt/nzqr5YxmfVdXb2aQV53VS/mm3pB2H\n' + 55 'iIt9FmvFaaOVe2DupqSr6xzbf/zyON+WF5B5HNVOWXswgpgdUsCyygs98hKy/Xje\n' + 56 'TGzJUoWInW39t0YgMXenJrkS0m6wol8Rhxx81AGgELNV7EHZqg==\n' + 57 '-----END PRIVATE KEY-----', 58 format: 'pem' 59}); 60const alicePublicKey = crypto.createPublicKey({ 61 key: '-----BEGIN PUBLIC KEY-----\n' + 62 'MIIBnzCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n' + 63 '0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n' + 64 'ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n' + 65 'PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n' + 66 'bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxAACgcBR7+iL5qx7aOb9K+aZ\n' + 67 'y2oLt7ST33sDKT+nxpag6cWDDWzPBKFDCJ8fr0v7yW453px8N4qi4R7SYYxFBaYN\n' + 68 'Y3JvgDg1ct2JC9sxSuUOLqSFn3hpmAjW7cS0kExIVGfdLlYtIqbhhuo45cTEbVIM\n' + 69 'rDEz8mjIlnvbWpKB9+uYmbjfVoc3leFvUBqfG2In2m23Md1swsPxr3n7g68H66JX\n' + 70 'iBJKZLQMqNdbY14G9rdKmhhTJrQjC+i7Q/wI8JPhOFzHIGA=\n' + 71 '-----END PUBLIC KEY-----', 72 format: 'pem' 73}); 74 75const bobPrivateKey = crypto.createPrivateKey({ 76 key: '-----BEGIN PRIVATE KEY-----\n' + 77 'MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n' + 78 'gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n' + 79 'bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n' + 80 '7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n' + 81 'cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwHxnT7Zw2Ehh1vyw\n' + 82 'eolzQFHQzyuT0y+3BF+FxK2Ox7VPguTp57wQfGHbORJ2cwCdLx2mFM7gk4tZ6COS\n' + 83 'E3Vta85a/PuhKXNLRdP79JgLnNtVtKXB+ePDS5C2GgXH1RHvqEdJh7JYnMy7Zj4P\n' + 84 'GagGtIy3dV5f4FA0B/2C97jQ1pO16ah8gSLQRKsNpTCw2rqsZusE0rK6RaYAef7H\n' + 85 'y/0tmLIsHxLIn+WK9CANqMbCWoP4I178BQaqhiOBkNyNZ0ndqA==\n' + 86 '-----END PRIVATE KEY-----', 87 format: 'pem' 88}); 89 90const bobPublicKey = crypto.createPublicKey({ 91 key: '-----BEGIN PUBLIC KEY-----\n' + 92 'MIIBoDCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n' + 93 '0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n' + 94 'ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n' + 95 'PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n' + 96 'bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxQACgcEAi26oq8z/GNSBm3zi\n' + 97 'gNt7SA7cArUBbTxINa9iLYWp6bxrvCKwDQwISN36/QUw8nUAe8aRyMt0oYn+y6vW\n' + 98 'Pw5OlO+TLrUelMVFaADEzoYomH0zVGb0sW4aBN8haC0mbrPt9QshgCvjr1hEPEna\n' + 99 'QFKfjzNaJRNMFFd4f2Dn8MSB4yu1xpA1T2i0JSk24vS2H55jx24xhUYtfhT2LJgK\n' + 100 'JvnaODey/xtY4Kql10ZKf43Lw6gdQC3G8opC9OxVxt9oNR7Z\n' + 101 '-----END PUBLIC KEY-----', 102 format: 'pem' 103}); 104 105assert.throws(() => crypto.diffieHellman({ privateKey: alicePrivateKey }), { 106 name: 'TypeError', 107 code: 'ERR_INVALID_ARG_VALUE', 108 message: "The property 'options.publicKey' is invalid. Received undefined" 109}); 110 111assert.throws(() => crypto.diffieHellman({ publicKey: alicePublicKey }), { 112 name: 'TypeError', 113 code: 'ERR_INVALID_ARG_VALUE', 114 message: "The property 'options.privateKey' is invalid. Received undefined" 115}); 116 117const privateKey = Buffer.from( 118 '487CD880159D835FD0A8DBA9848898317283DB07E822741B344AD397BA84CDDD3920A51588' + 119 'B891B03B3EBEF3C9F767D921FAC1294D4B5E09CABB6D1DE3EB4527989754FEB64D007EBBDA' + 120 '2E6C8CE7A17EF41DE3C2DFE7CEAAF963199F55D5DBD9A415E77552FE69B7A41D87888B7D16' + 121 '6BC569A3957B60EEA6A4ABEB1CDB7FFCF238DF961790791CD54E597B3082981D52C0B2CA0B' + 122 '3DF212B2FD78DE4C6CC95285889D6DFDB746203177A726B912D26EB0A25F11871C7CD401A0' + 123 '10B355EC41D9AA', 'hex'); 124const publicKey = Buffer.from( 125 '8b6ea8abccff18d4819b7ce280db7b480edc02b5016d3c4835af622d85a9e9bc6bbc22b00d' + 126 '0c0848ddfafd0530f275007bc691c8cb74a189fecbabd63f0e4e94ef932eb51e94c5456800' + 127 'c4ce8628987d335466f4b16e1a04df21682d266eb3edf50b21802be3af58443c49da40529f' + 128 '8f335a25134c1457787f60e7f0c481e32bb5c690354f68b4252936e2f4b61f9e63c76e3185' + 129 '462d7e14f62c980a26f9da3837b2ff1b58e0aaa5d7464a7f8dcbc3a81d402dc6f28a42f4ec' + 130 '55c6df68351ed9', 'hex'); 131 132const group = crypto.getDiffieHellman('modp5'); 133const dh = crypto.createDiffieHellman(group.getPrime(), group.getGenerator()); 134dh.setPrivateKey(privateKey); 135 136// Test simple Diffie-Hellman, no curves involved. 137test({ publicKey: alicePublicKey, privateKey: alicePrivateKey }, 138 { publicKey: bobPublicKey, privateKey: bobPrivateKey }, 139 dh.computeSecret(publicKey)); 140 141test(crypto.generateKeyPairSync('dh', { group: 'modp5' }), 142 crypto.generateKeyPairSync('dh', { group: 'modp5' })); 143 144test(crypto.generateKeyPairSync('dh', { group: 'modp5' }), 145 crypto.generateKeyPairSync('dh', { prime: group.getPrime() })); 146 147const list = [ 148 // Same generator, but different primes. 149 [{ group: 'modp5' }, { group: 'modp18' }]]; 150 151// TODO(danbev): Take a closer look if there should be a check in OpenSSL3 152// when the dh parameters differ. 153if (!common.hasOpenSSL3) { 154 // Same primes, but different generator. 155 list.push([{ group: 'modp5' }, { prime: group.getPrime(), generator: 5 }]); 156 // Same generator, but different primes. 157 list.push([{ primeLength: 1024 }, { primeLength: 1024 }]); 158} 159 160for (const [params1, params2] of list) { 161 assert.throws(() => { 162 test(crypto.generateKeyPairSync('dh', params1), 163 crypto.generateKeyPairSync('dh', params2)); 164 }, common.hasOpenSSL3 ? { 165 name: 'Error', 166 code: 'ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS' 167 } : { 168 name: 'Error', 169 code: 'ERR_OSSL_EVP_DIFFERENT_PARAMETERS' 170 }); 171} 172{ 173 const privateKey = crypto.createPrivateKey({ 174 key: '-----BEGIN PRIVATE KEY-----\n' + 175 'MIIBoQIBADCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKL\n' + 176 'gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt\n' + 177 'bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR\n' + 178 '7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH\n' + 179 'cJaWbWcMNU5KvJgE8XRsCMojcyf//////////wIBAgSBwwKBwHu9fpiqrfJJ+tl9\n' + 180 'ujFtEWv4afub6A/1/7sgishOYN3YQ+nmWQlmPpveIY34an5dG82CTrixHwUzQTMF\n' + 181 'JaiCW3ax9+qk31f2jTNKrQznmKgopVKXF0FEJC6H79W/8Y0U14gsI9sHpovKhfou\n' + 182 'RQD0QogW7ejSwMG8hCYibfrvMm0b5PHlwimISyEKh7VtDQ1frYN/Wr9ZbiV+FePJ\n' + 183 '2j6RUKYNj1Pv+B4zdMgiLLjILAs8WUfbHciU21KSJh1izVQaUQ==\n' + 184 '-----END PRIVATE KEY-----' 185 }); 186 const publicKey = crypto.createPublicKey({ 187 key: '-----BEGIN PUBLIC KEY-----\n' + 188 'MIIBoDCB1QYJKoZIhvcNAQMBMIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc\n' + 189 '0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHC\n' + 190 'ReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORb\n' + 191 'PcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaW\n' + 192 'bWcMNU5KvJgE8XRsCMojcyf//////////wIBAgOBxQACgcEAmG9LpD8SAA6/W7oK\n' + 193 'E4MCuuQtf5E8bqtcEAfYTOOvKyCS+eiX3TtZRsvHJjUBEyeO99PR/KrGVlkSuW52\n' + 194 'ZOSXUOFu1L/0tqHrvRVHo+QEq3OvZ3EAyJkdtSEUTztxuUrMOyJXHDc1OUdNSnk0\n' + 195 'taGX4mP3247golVx2DS4viDYs7UtaMdx03dWaP6y5StNUZQlgCIUzL7MYpC16V5y\n' + 196 'KkFrE+Kp/Z77gEjivaG6YuxVj4GPLxJYbNFVTel42oSVeKuq\n' + 197 '-----END PUBLIC KEY-----', 198 format: 'pem' 199 }); 200 201 // This key combination will result in an unusually short secret, and should 202 // not cause an assertion failure. 203 const secret = crypto.diffieHellman({ publicKey, privateKey }); 204 assert.strictEqual(secret.toString('hex'), 205 '0099d0fa242af5db9ea7330e23937a27db041f79c581500fc7f9976' + 206 '554d59d5b9ced934778d72e19a1fefc81e9d981013198748c0b5c6c' + 207 '762985eec687dc5bec5c9367b05837daee9d0bcc29024ed7f3abba1' + 208 '2794b65a745117fb0d87bc5b1b2b68c296c3f686cc29e450e4e1239' + 209 '21f56a5733fe58aabf71f14582954059c2185d342b9b0fa10c2598a' + 210 '5426c2baee7f9a686fc1e16cd4757c852bf7225a2732250548efe28' + 211 'debc26f1acdec51efe23d20786a6f8a14d360803bbc71972e87fd3'); 212} 213 214// Test ECDH. 215 216test(crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' }), 217 crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' })); 218 219const not256k1 = crypto.getCurves().find((c) => /^sec.*(224|384|512)/.test(c)); 220assert.throws(() => { 221 test(crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' }), 222 crypto.generateKeyPairSync('ec', { namedCurve: not256k1 })); 223}, common.hasOpenSSL3 ? { 224 name: 'Error', 225 code: 'ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS' 226} : { 227 name: 'Error', 228 code: 'ERR_OSSL_EVP_DIFFERENT_PARAMETERS' 229}); 230 231// Test ECDH-ES. 232 233test(crypto.generateKeyPairSync('x448'), 234 crypto.generateKeyPairSync('x448')); 235 236test(crypto.generateKeyPairSync('x25519'), 237 crypto.generateKeyPairSync('x25519')); 238 239assert.throws(() => { 240 test(crypto.generateKeyPairSync('x448'), 241 crypto.generateKeyPairSync('x25519')); 242}, { 243 name: 'Error', 244 code: 'ERR_CRYPTO_INCOMPATIBLE_KEY', 245 message: 'Incompatible key types for Diffie-Hellman: x448 and x25519' 246}); 247