| 'use strict'; |
| const common = require('../common'); |
| if (!common.hasCrypto) |
| common.skip('missing crypto'); |
| |
| const assert = require('assert'); |
| const util = require('util'); |
| const crypto = require('crypto'); |
| const fixtures = require('../common/fixtures'); |
| |
| function test( |
| publicFixture, |
| privateFixture, |
| algorithm, |
| deterministic, |
| options |
| ) { |
| let publicPem = fixtures.readKey(publicFixture); |
| let privatePem = fixtures.readKey(privateFixture); |
| let privateKey = crypto.createPrivateKey(privatePem); |
| let publicKey = crypto.createPublicKey(publicPem); |
| const privateDer = { |
| key: privateKey.export({ format: 'der', type: 'pkcs8' }), |
| format: 'der', |
| type: 'pkcs8', |
| ...options |
| }; |
| const publicDer = { |
| key: publicKey.export({ format: 'der', type: 'spki' }), |
| format: 'der', |
| type: 'spki', |
| ...options |
| }; |
| |
| if (options) { |
| publicPem = { ...options, key: publicPem }; |
| privatePem = { ...options, key: privatePem }; |
| privateKey = { ...options, key: privateKey }; |
| publicKey = { ...options, key: publicKey }; |
| } |
| |
| const data = Buffer.from('Hello world'); |
| const expected = crypto.sign(algorithm, data, privateKey); |
| |
| for (const key of [privatePem, privateKey, privateDer]) { |
| crypto.sign(algorithm, data, key, common.mustSucceed((actual) => { |
| if (deterministic) { |
| assert.deepStrictEqual(actual, expected); |
| } |
| |
| assert.strictEqual( |
| crypto.verify(algorithm, data, key, actual), true); |
| })); |
| } |
| |
| const verifyInputs = [ |
| publicPem, publicKey, publicDer, privatePem, privateKey, privateDer]; |
| for (const key of verifyInputs) { |
| crypto.verify(algorithm, data, key, expected, common.mustSucceed( |
| (verified) => assert.strictEqual(verified, true))); |
| |
| crypto.verify(algorithm, data, key, Buffer.from(''), common.mustSucceed( |
| (verified) => assert.strictEqual(verified, false))); |
| } |
| } |
| |
| // RSA w/ default padding |
| test('rsa_public.pem', 'rsa_private.pem', 'sha256', true); |
| test('rsa_public.pem', 'rsa_private.pem', 'sha256', true, |
| { padding: crypto.constants.RSA_PKCS1_PADDING }); |
| |
| // RSA w/ PSS_PADDING and default saltLength |
| test('rsa_public.pem', 'rsa_private.pem', 'sha256', false, |
| { padding: crypto.constants.RSA_PKCS1_PSS_PADDING }); |
| test('rsa_public.pem', 'rsa_private.pem', 'sha256', false, |
| { |
| padding: crypto.constants.RSA_PKCS1_PSS_PADDING, |
| saltLength: crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN |
| }); |
| |
| // RSA w/ PSS_PADDING and PSS_SALTLEN_DIGEST |
| test('rsa_public.pem', 'rsa_private.pem', 'sha256', false, |
| { |
| padding: crypto.constants.RSA_PKCS1_PSS_PADDING, |
| saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST |
| }); |
| |
| // ED25519 |
| test('ed25519_public.pem', 'ed25519_private.pem', undefined, true); |
| // ED448 |
| test('ed448_public.pem', 'ed448_private.pem', undefined, true); |
| |
| // ECDSA w/ der signature encoding |
| test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384', |
| false); |
| test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384', |
| false, { dsaEncoding: 'der' }); |
| |
| // ECDSA w/ ieee-p1363 signature encoding |
| test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384', false, |
| { dsaEncoding: 'ieee-p1363' }); |
| |
| // DSA w/ der signature encoding |
| test('dsa_public.pem', 'dsa_private.pem', 'sha256', |
| false); |
| test('dsa_public.pem', 'dsa_private.pem', 'sha256', |
| false, { dsaEncoding: 'der' }); |
| |
| // DSA w/ ieee-p1363 signature encoding |
| test('dsa_public.pem', 'dsa_private.pem', 'sha256', false, |
| { dsaEncoding: 'ieee-p1363' }); |
| |
| // Test Parallel Execution w/ KeyObject is threadsafe in openssl3 |
| { |
| const publicKey = { |
| key: crypto.createPublicKey( |
| fixtures.readKey('ec_p256_public.pem')), |
| dsaEncoding: 'ieee-p1363', |
| }; |
| const privateKey = { |
| key: crypto.createPrivateKey( |
| fixtures.readKey('ec_p256_private.pem')), |
| dsaEncoding: 'ieee-p1363', |
| }; |
| |
| const sign = util.promisify(crypto.sign); |
| const verify = util.promisify(crypto.verify); |
| |
| const data = Buffer.from('hello world'); |
| |
| Promise.all([ |
| sign('sha256', data, privateKey), |
| sign('sha256', data, privateKey), |
| sign('sha256', data, privateKey), |
| ]).then(([signature]) => { |
| return Promise.all([ |
| verify('sha256', data, publicKey, signature), |
| verify('sha256', data, publicKey, signature), |
| verify('sha256', data, publicKey, signature), |
| ]).then(common.mustCall()); |
| }) |
| .catch(common.mustNotCall()); |
| } |