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