| 'use strict'; |
| const common = require('../common'); |
| if (!common.hasCrypto) { |
| common.skip('missing crypto'); |
| } |
| |
| const assert = require('assert'); |
| const crypto = require('crypto'); |
| const { |
| hasOpenSSL3, |
| } = require('../common/crypto'); |
| |
| { |
| const size = crypto.getFips() || hasOpenSSL3 ? 1024 : 256; |
| const dh1 = crypto.createDiffieHellman(size); |
| const p1 = dh1.getPrime('buffer'); |
| const dh2 = crypto.createDiffieHellman(p1, 'buffer'); |
| const key1 = dh1.generateKeys(); |
| const key2 = dh2.generateKeys('hex'); |
| const secret1 = dh1.computeSecret(key2, 'hex', 'base64'); |
| const secret2 = dh2.computeSecret(key1, 'latin1', 'buffer'); |
| |
| // Test Diffie-Hellman with two parties sharing a secret, |
| // using various encodings as we go along |
| assert.strictEqual(secret2.toString('base64'), secret1); |
| assert.strictEqual(dh1.verifyError, 0); |
| assert.strictEqual(dh2.verifyError, 0); |
| |
| // Create "another dh1" using generated keys from dh1, |
| // and compute secret again |
| const dh3 = crypto.createDiffieHellman(p1, 'buffer'); |
| const privkey1 = dh1.getPrivateKey(); |
| dh3.setPublicKey(key1); |
| dh3.setPrivateKey(privkey1); |
| |
| assert.deepStrictEqual(dh1.getPrime(), dh3.getPrime()); |
| assert.deepStrictEqual(dh1.getGenerator(), dh3.getGenerator()); |
| assert.deepStrictEqual(dh1.getPublicKey(), dh3.getPublicKey()); |
| assert.deepStrictEqual(dh1.getPrivateKey(), dh3.getPrivateKey()); |
| assert.strictEqual(dh3.verifyError, 0); |
| |
| const secret3 = dh3.computeSecret(key2, 'hex', 'base64'); |
| |
| assert.strictEqual(secret1, secret3); |
| |
| // computeSecret works without a public key set at all. |
| const dh4 = crypto.createDiffieHellman(p1, 'buffer'); |
| dh4.setPrivateKey(privkey1); |
| |
| assert.deepStrictEqual(dh1.getPrime(), dh4.getPrime()); |
| assert.deepStrictEqual(dh1.getGenerator(), dh4.getGenerator()); |
| assert.deepStrictEqual(dh1.getPrivateKey(), dh4.getPrivateKey()); |
| assert.strictEqual(dh4.verifyError, 0); |
| |
| const secret4 = dh4.computeSecret(key2, 'hex', 'base64'); |
| |
| assert.strictEqual(secret1, secret4); |
| |
| let wrongBlockLength; |
| if (hasOpenSSL3) { |
| wrongBlockLength = { |
| message: /wrong[\s_]final[\s_]block[\s_]length/i, |
| code: /ERR_OSSL_(EVP_)?WRONG_FINAL_BLOCK_LENGTH/, |
| library: /Provider routines|Cipher functions/, |
| reason: /wrong[\s_]final[\s_]block[\s_]length/i, |
| }; |
| } else { |
| wrongBlockLength = { |
| message: /wrong[\s_]final[\s_]block[\s_]length/i, |
| code: /ERR_OSSL_(EVP_)?WRONG_FINAL_BLOCK_LENGTH/, |
| library: /digital envelope routines|Cipher functions/, |
| reason: /wrong[\s_]final[\s_]block[\s_]length/i, |
| }; |
| } |
| |
| // Run this one twice to make sure that the dh3 clears its error properly |
| { |
| const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); |
| assert.throws(() => { |
| c.final('utf8'); |
| }, wrongBlockLength); |
| } |
| |
| { |
| const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); |
| assert.throws(() => { |
| c.final('utf8'); |
| }, wrongBlockLength); |
| } |
| |
| { |
| assert.throws(() => { |
| dh3.computeSecret(''); |
| }, { message: process.features.openssl_is_boringssl ? |
| 'Supplied key is invalid' : |
| 'Supplied key is too small' }); |
| } |
| } |
| |
| // Through a fluke of history, g=0 defaults to DH_GENERATOR (2). |
| { |
| const g = 0; |
| if (process.features.openssl_is_boringssl) { |
| assert.throws(() => crypto.createDiffieHellman('abcdef', g), { |
| code: 'ERR_CRYPTO_OPERATION_FAILED', |
| name: 'Error' |
| }); |
| } else { |
| crypto.createDiffieHellman('abcdef', g); |
| } |
| crypto.createDiffieHellman('abcdef', 'hex', g); |
| } |
| |
| { |
| if (process.features.openssl_is_boringssl) { |
| assert.throws(() => crypto.createDiffieHellman('abcdef', Buffer.from([2])), { |
| code: 'ERR_CRYPTO_OPERATION_FAILED', |
| name: 'Error' |
| }); |
| } else { |
| crypto.createDiffieHellman('abcdef', Buffer.from([2])); // OK |
| } |
| } |