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