• 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
9{
10  const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256;
11  const dh1 = crypto.createDiffieHellman(size);
12  const p1 = dh1.getPrime('buffer');
13  const dh2 = crypto.createDiffieHellman(p1, 'buffer');
14  const key1 = dh1.generateKeys();
15  const key2 = dh2.generateKeys('hex');
16  const secret1 = dh1.computeSecret(key2, 'hex', 'base64');
17  const secret2 = dh2.computeSecret(key1, 'latin1', 'buffer');
18
19  // Test Diffie-Hellman with two parties sharing a secret,
20  // using various encodings as we go along
21  assert.strictEqual(secret2.toString('base64'), secret1);
22  assert.strictEqual(dh1.verifyError, 0);
23  assert.strictEqual(dh2.verifyError, 0);
24
25  // Create "another dh1" using generated keys from dh1,
26  // and compute secret again
27  const dh3 = crypto.createDiffieHellman(p1, 'buffer');
28  const privkey1 = dh1.getPrivateKey();
29  dh3.setPublicKey(key1);
30  dh3.setPrivateKey(privkey1);
31
32  assert.deepStrictEqual(dh1.getPrime(), dh3.getPrime());
33  assert.deepStrictEqual(dh1.getGenerator(), dh3.getGenerator());
34  assert.deepStrictEqual(dh1.getPublicKey(), dh3.getPublicKey());
35  assert.deepStrictEqual(dh1.getPrivateKey(), dh3.getPrivateKey());
36  assert.strictEqual(dh3.verifyError, 0);
37
38  const secret3 = dh3.computeSecret(key2, 'hex', 'base64');
39
40  assert.strictEqual(secret1, secret3);
41
42  // computeSecret works without a public key set at all.
43  const dh4 = crypto.createDiffieHellman(p1, 'buffer');
44  dh4.setPrivateKey(privkey1);
45
46  assert.deepStrictEqual(dh1.getPrime(), dh4.getPrime());
47  assert.deepStrictEqual(dh1.getGenerator(), dh4.getGenerator());
48  assert.deepStrictEqual(dh1.getPrivateKey(), dh4.getPrivateKey());
49  assert.strictEqual(dh4.verifyError, 0);
50
51  const secret4 = dh4.computeSecret(key2, 'hex', 'base64');
52
53  assert.strictEqual(secret1, secret4);
54
55  let wrongBlockLength;
56  if (common.hasOpenSSL3) {
57    wrongBlockLength = {
58      message: 'error:1C80006B:Provider routines::wrong final block length',
59      code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH',
60      library: 'Provider routines',
61      reason: 'wrong final block length'
62    };
63  } else {
64    wrongBlockLength = {
65      message: 'error:0606506D:digital envelope' +
66        ' routines:EVP_DecryptFinal_ex:wrong final block length',
67      code: 'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH',
68      library: 'digital envelope routines',
69      reason: 'wrong final block length'
70    };
71  }
72
73  // Run this one twice to make sure that the dh3 clears its error properly
74  {
75    const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), '');
76    assert.throws(() => {
77      c.final('utf8');
78    }, wrongBlockLength);
79  }
80
81  {
82    const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), '');
83    assert.throws(() => {
84      c.final('utf8');
85    }, wrongBlockLength);
86  }
87
88  {
89    const v = crypto.constants.OPENSSL_VERSION_NUMBER;
90    const hasOpenSSL3WithNewErrorMessage = (v >= 0x300000c0 && v <= 0x30100000) || (v >= 0x30100040 && v <= 0x30200000);
91    assert.throws(() => {
92      dh3.computeSecret('');
93    }, { message: common.hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ?
94      'error:02800080:Diffie-Hellman routines::invalid secret' :
95      'Supplied key is too small' });
96  }
97}
98
99// Through a fluke of history, g=0 defaults to DH_GENERATOR (2).
100{
101  const g = 0;
102  crypto.createDiffieHellman('abcdef', g);
103  crypto.createDiffieHellman('abcdef', 'hex', g);
104}
105
106{
107  crypto.createDiffieHellman('abcdef', Buffer.from([2]));  // OK
108}
109