1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5
6const assert = require('assert');
7const util = require('util');
8const crypto = require('crypto');
9const fixtures = require('../common/fixtures');
10
11function test(
12  publicFixture,
13  privateFixture,
14  algorithm,
15  deterministic,
16  options
17) {
18  let publicPem = fixtures.readKey(publicFixture);
19  let privatePem = fixtures.readKey(privateFixture);
20  let privateKey = crypto.createPrivateKey(privatePem);
21  let publicKey = crypto.createPublicKey(publicPem);
22  const privateDer = {
23    key: privateKey.export({ format: 'der', type: 'pkcs8' }),
24    format: 'der',
25    type: 'pkcs8',
26    ...options
27  };
28  const publicDer = {
29    key: publicKey.export({ format: 'der', type: 'spki' }),
30    format: 'der',
31    type: 'spki',
32    ...options
33  };
34
35  if (options) {
36    publicPem = { ...options, key: publicPem };
37    privatePem = { ...options, key: privatePem };
38    privateKey = { ...options, key: privateKey };
39    publicKey = { ...options, key: publicKey };
40  }
41
42  const data = Buffer.from('Hello world');
43  const expected = crypto.sign(algorithm, data, privateKey);
44
45  for (const key of [privatePem, privateKey, privateDer]) {
46    crypto.sign(algorithm, data, key, common.mustSucceed((actual) => {
47      if (deterministic) {
48        assert.deepStrictEqual(actual, expected);
49      }
50
51      assert.strictEqual(
52        crypto.verify(algorithm, data, key, actual), true);
53    }));
54  }
55
56  const verifyInputs = [
57    publicPem, publicKey, publicDer, privatePem, privateKey, privateDer];
58  for (const key of verifyInputs) {
59    crypto.verify(algorithm, data, key, expected, common.mustSucceed(
60      (verified) => assert.strictEqual(verified, true)));
61
62    crypto.verify(algorithm, data, key, Buffer.from(''), common.mustSucceed(
63      (verified) => assert.strictEqual(verified, false)));
64  }
65}
66
67// RSA w/ default padding
68test('rsa_public.pem', 'rsa_private.pem', 'sha256', true);
69test('rsa_public.pem', 'rsa_private.pem', 'sha256', true,
70     { padding: crypto.constants.RSA_PKCS1_PADDING });
71
72// RSA w/ PSS_PADDING and default saltLength
73test('rsa_public.pem', 'rsa_private.pem', 'sha256', false,
74     { padding: crypto.constants.RSA_PKCS1_PSS_PADDING });
75test('rsa_public.pem', 'rsa_private.pem', 'sha256', false,
76     {
77       padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
78       saltLength: crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN
79     });
80
81// RSA w/ PSS_PADDING and PSS_SALTLEN_DIGEST
82test('rsa_public.pem', 'rsa_private.pem', 'sha256', false,
83     {
84       padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
85       saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST
86     });
87
88// ED25519
89test('ed25519_public.pem', 'ed25519_private.pem', undefined, true);
90// ED448
91test('ed448_public.pem', 'ed448_private.pem', undefined, true);
92
93// ECDSA w/ der signature encoding
94test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384',
95     false);
96test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384',
97     false, { dsaEncoding: 'der' });
98
99// ECDSA w/ ieee-p1363 signature encoding
100test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384', false,
101     { dsaEncoding: 'ieee-p1363' });
102
103// DSA w/ der signature encoding
104test('dsa_public.pem', 'dsa_private.pem', 'sha256',
105     false);
106test('dsa_public.pem', 'dsa_private.pem', 'sha256',
107     false, { dsaEncoding: 'der' });
108
109// DSA w/ ieee-p1363 signature encoding
110test('dsa_public.pem', 'dsa_private.pem', 'sha256', false,
111     { dsaEncoding: 'ieee-p1363' });
112
113// Test Parallel Execution w/ KeyObject is threadsafe in openssl3
114{
115  const publicKey = {
116    key: crypto.createPublicKey(
117      fixtures.readKey('ec_p256_public.pem')),
118    dsaEncoding: 'ieee-p1363',
119  };
120  const privateKey = {
121    key: crypto.createPrivateKey(
122      fixtures.readKey('ec_p256_private.pem')),
123    dsaEncoding: 'ieee-p1363',
124  };
125
126  const sign = util.promisify(crypto.sign);
127  const verify = util.promisify(crypto.verify);
128
129  const data = Buffer.from('hello world');
130
131  Promise.all([
132    sign('sha256', data, privateKey),
133    sign('sha256', data, privateKey),
134    sign('sha256', data, privateKey),
135  ]).then(([signature]) => {
136    return Promise.all([
137      verify('sha256', data, publicKey, signature),
138      verify('sha256', data, publicKey, signature),
139      verify('sha256', data, publicKey, signature),
140    ]).then(common.mustCall());
141  })
142  .catch(common.mustNotCall());
143}
144