mirror of
https://github.com/nodejs/node.git
synced 2025-08-16 14:18:44 +02:00

Since `common/crypto` already exists, it makes sense to keep crypto-related utilities there. The only exception being common.hasCrypto which is needed up front to determine if tests should be skipped. Eliminate the redundant check in hasFipsCrypto and just use crypto.getFips() directly where needed. PR-URL: https://github.com/nodejs/node/pull/56714 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
821 lines
22 KiB
JavaScript
821 lines
22 KiB
JavaScript
'use strict';
|
|
|
|
// This tests early errors for invalid encodings.
|
|
|
|
const common = require('../common');
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const assert = require('assert');
|
|
|
|
const {
|
|
generateKeyPair,
|
|
generateKeyPairSync,
|
|
} = require('crypto');
|
|
const { inspect } = require('util');
|
|
|
|
const { hasOpenSSL3 } = require('../common/crypto');
|
|
|
|
// Test invalid parameter encoding.
|
|
{
|
|
assert.throws(() => generateKeyPairSync('ec', {
|
|
namedCurve: 'P-256',
|
|
paramEncoding: 'otherEncoding',
|
|
publicKeyEncoding: {
|
|
type: 'spki',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs8',
|
|
format: 'pem',
|
|
cipher: 'aes-128-cbc',
|
|
passphrase: 'top secret'
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.paramEncoding' is invalid. " +
|
|
"Received 'otherEncoding'"
|
|
});
|
|
}
|
|
|
|
{
|
|
// Test invalid key types.
|
|
for (const type of [undefined, null, 0]) {
|
|
assert.throws(() => generateKeyPairSync(type, {}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: 'The "type" argument must be of type string.' +
|
|
common.invalidArgTypeHelper(type)
|
|
});
|
|
}
|
|
|
|
assert.throws(() => generateKeyPairSync('rsa2', {}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The argument 'type' must be a supported key type. Received 'rsa2'"
|
|
});
|
|
}
|
|
|
|
{
|
|
// Test keygen without options object.
|
|
assert.throws(() => generateKeyPair('rsa', common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: 'The "options" argument must be of type object. ' +
|
|
'Received undefined'
|
|
});
|
|
|
|
// Even if no options are required, it should be impossible to pass anything
|
|
// but an object (or undefined).
|
|
assert.throws(() => generateKeyPair('ed448', 0, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: 'The "options" argument must be of type object. ' +
|
|
'Received type number (0)'
|
|
});
|
|
}
|
|
|
|
{
|
|
// Invalid publicKeyEncoding.
|
|
for (const enc of [0, 'a', true]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: enc,
|
|
privateKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.publicKeyEncoding' is invalid. " +
|
|
`Received ${inspect(enc)}`
|
|
});
|
|
}
|
|
|
|
// Missing publicKeyEncoding.type.
|
|
for (const type of [undefined, null, 0, true, {}]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type,
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.publicKeyEncoding.type' is invalid. " +
|
|
`Received ${inspect(type)}`
|
|
});
|
|
}
|
|
|
|
// Missing / invalid publicKeyEncoding.format.
|
|
for (const format of [undefined, null, 0, false, 'a', {}]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.publicKeyEncoding.format' is invalid. " +
|
|
`Received ${inspect(format)}`
|
|
});
|
|
}
|
|
|
|
// Invalid privateKeyEncoding.
|
|
for (const enc of [0, 'a', true]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: enc
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.privateKeyEncoding' is invalid. " +
|
|
`Received ${inspect(enc)}`
|
|
});
|
|
}
|
|
|
|
// Missing / invalid privateKeyEncoding.type.
|
|
for (const type of [undefined, null, 0, true, {}]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type,
|
|
format: 'pem'
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.privateKeyEncoding.type' is invalid. " +
|
|
`Received ${inspect(type)}`
|
|
});
|
|
}
|
|
|
|
// Missing / invalid privateKeyEncoding.format.
|
|
for (const format of [undefined, null, 0, false, 'a', {}]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.privateKeyEncoding.format' is invalid. " +
|
|
`Received ${inspect(format)}`
|
|
});
|
|
}
|
|
|
|
// Cipher of invalid type.
|
|
for (const cipher of [0, true, {}]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem',
|
|
cipher
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.privateKeyEncoding.cipher' is invalid. " +
|
|
`Received ${inspect(cipher)}`
|
|
});
|
|
}
|
|
|
|
// Invalid cipher.
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs8',
|
|
format: 'pem',
|
|
cipher: 'foo',
|
|
passphrase: 'secret'
|
|
}
|
|
}), {
|
|
name: 'Error',
|
|
code: 'ERR_CRYPTO_UNKNOWN_CIPHER',
|
|
message: 'Unknown cipher'
|
|
});
|
|
|
|
// Cipher, but no valid passphrase.
|
|
for (const passphrase of [undefined, null, 5, false, true]) {
|
|
assert.throws(() => generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: {
|
|
type: 'pkcs1',
|
|
format: 'pem'
|
|
},
|
|
privateKeyEncoding: {
|
|
type: 'pkcs8',
|
|
format: 'pem',
|
|
cipher: 'aes-128-cbc',
|
|
passphrase
|
|
}
|
|
}), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.privateKeyEncoding.passphrase' " +
|
|
`is invalid. Received ${inspect(passphrase)}`
|
|
});
|
|
}
|
|
|
|
// Test invalid callbacks.
|
|
for (const cb of [undefined, null, 0, {}]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength: 512,
|
|
publicKeyEncoding: { type: 'pkcs1', format: 'pem' },
|
|
privateKeyEncoding: { type: 'pkcs1', format: 'pem' }
|
|
}, cb), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Test RSA parameters.
|
|
{
|
|
// Test invalid modulus lengths. (non-number)
|
|
for (const modulusLength of [undefined, null, 'a', true, {}, []]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength
|
|
}, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.modulusLength" property must be of type number.' +
|
|
common.invalidArgTypeHelper(modulusLength)
|
|
});
|
|
}
|
|
|
|
// Test invalid modulus lengths. (non-integer)
|
|
for (const modulusLength of [512.1, 1.3, 1.1, 5000.9, 100.5]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message:
|
|
'The value of "options.modulusLength" is out of range. ' +
|
|
'It must be an integer. ' +
|
|
`Received ${inspect(modulusLength)}`
|
|
});
|
|
}
|
|
|
|
// Test invalid modulus lengths. (out of range)
|
|
for (const modulusLength of [-1, -9, 4294967297]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
});
|
|
}
|
|
|
|
// Test invalid exponents. (non-number)
|
|
for (const publicExponent of ['a', true, {}, []]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength: 4096,
|
|
publicExponent
|
|
}, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.publicExponent" property must be of type number.' +
|
|
common.invalidArgTypeHelper(publicExponent)
|
|
});
|
|
}
|
|
|
|
// Test invalid exponents. (non-integer)
|
|
for (const publicExponent of [3.5, 1.1, 50.5, 510.5]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength: 4096,
|
|
publicExponent
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message:
|
|
'The value of "options.publicExponent" is out of range. ' +
|
|
'It must be an integer. ' +
|
|
`Received ${inspect(publicExponent)}`
|
|
});
|
|
}
|
|
|
|
// Test invalid exponents. (out of range)
|
|
for (const publicExponent of [-5, -3, 4294967297]) {
|
|
assert.throws(() => generateKeyPair('rsa', {
|
|
modulusLength: 4096,
|
|
publicExponent
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
});
|
|
}
|
|
|
|
// Test invalid exponents. (caught by OpenSSL)
|
|
for (const publicExponent of [1, 1 + 0x10001]) {
|
|
generateKeyPair('rsa', {
|
|
modulusLength: 4096,
|
|
publicExponent
|
|
}, common.mustCall((err) => {
|
|
assert.strictEqual(err.name, 'Error');
|
|
assert.match(err.message, hasOpenSSL3 ? /exponent/ : /bad e value/);
|
|
}));
|
|
}
|
|
}
|
|
|
|
// Test DSA parameters.
|
|
{
|
|
// Test invalid modulus lengths. (non-number)
|
|
for (const modulusLength of [undefined, null, 'a', true, {}, []]) {
|
|
assert.throws(() => generateKeyPair('dsa', {
|
|
modulusLength
|
|
}, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.modulusLength" property must be of type number.' +
|
|
common.invalidArgTypeHelper(modulusLength)
|
|
});
|
|
}
|
|
|
|
// Test invalid modulus lengths. (non-integer)
|
|
for (const modulusLength of [512.1, 1.3, 1.1, 5000.9, 100.5]) {
|
|
assert.throws(() => generateKeyPair('dsa', {
|
|
modulusLength
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
});
|
|
}
|
|
|
|
// Test invalid modulus lengths. (out of range)
|
|
for (const modulusLength of [-1, -9, 4294967297]) {
|
|
assert.throws(() => generateKeyPair('dsa', {
|
|
modulusLength
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
});
|
|
}
|
|
|
|
// Test invalid divisor lengths. (non-number)
|
|
for (const divisorLength of ['a', true, {}, []]) {
|
|
assert.throws(() => generateKeyPair('dsa', {
|
|
modulusLength: 2048,
|
|
divisorLength
|
|
}, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.divisorLength" property must be of type number.' +
|
|
common.invalidArgTypeHelper(divisorLength)
|
|
});
|
|
}
|
|
|
|
// Test invalid divisor lengths. (non-integer)
|
|
for (const divisorLength of [4096.1, 5.1, 6.9, 9.5]) {
|
|
assert.throws(() => generateKeyPair('dsa', {
|
|
modulusLength: 2048,
|
|
divisorLength
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message:
|
|
'The value of "options.divisorLength" is out of range. ' +
|
|
'It must be an integer. ' +
|
|
`Received ${inspect(divisorLength)}`
|
|
});
|
|
}
|
|
|
|
// Test invalid divisor lengths. (out of range)
|
|
for (const divisorLength of [-1, -6, -9, 2147483648]) {
|
|
assert.throws(() => generateKeyPair('dsa', {
|
|
modulusLength: 2048,
|
|
divisorLength
|
|
}, common.mustNotCall()), {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message:
|
|
'The value of "options.divisorLength" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
`Received ${inspect(divisorLength)}`
|
|
});
|
|
}
|
|
}
|
|
|
|
// Test EC parameters.
|
|
{
|
|
// Test invalid curves.
|
|
assert.throws(() => {
|
|
generateKeyPairSync('ec', {
|
|
namedCurve: 'abcdef',
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: { type: 'sec1', format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'TypeError',
|
|
message: 'Invalid EC curve name'
|
|
});
|
|
|
|
// Test error type when curve is not a string
|
|
for (const namedCurve of [true, {}, [], 123]) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync('ec', {
|
|
namedCurve,
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: { type: 'sec1', format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.namedCurve" property must be of type string.' +
|
|
common.invalidArgTypeHelper(namedCurve)
|
|
});
|
|
}
|
|
|
|
// It should recognize both NIST and standard curve names.
|
|
generateKeyPair('ec', {
|
|
namedCurve: 'P-256',
|
|
}, common.mustSucceed((publicKey, privateKey) => {
|
|
assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {
|
|
namedCurve: 'prime256v1'
|
|
});
|
|
assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {
|
|
namedCurve: 'prime256v1'
|
|
});
|
|
}));
|
|
|
|
generateKeyPair('ec', {
|
|
namedCurve: 'secp256k1',
|
|
}, common.mustSucceed((publicKey, privateKey) => {
|
|
assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {
|
|
namedCurve: 'secp256k1'
|
|
});
|
|
assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {
|
|
namedCurve: 'secp256k1'
|
|
});
|
|
}));
|
|
}
|
|
|
|
{
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', common.mustNotCall());
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: 'The "options" argument must be of type object. Received undefined'
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', {}, common.mustNotCall());
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_MISSING_OPTION',
|
|
message: 'At least one of the group, prime, or primeLength options is ' +
|
|
'required'
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', {
|
|
group: 'modp0'
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'Error',
|
|
code: 'ERR_CRYPTO_UNKNOWN_DH_GROUP',
|
|
message: 'Unknown DH group'
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', {
|
|
primeLength: 2147483648
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.primeLength" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
'Received 2147483648',
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', {
|
|
primeLength: -1
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.primeLength" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
'Received -1',
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', {
|
|
primeLength: 2,
|
|
generator: 2147483648,
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.generator" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
'Received 2147483648',
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('dh', {
|
|
primeLength: 2,
|
|
generator: -1,
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.generator" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
'Received -1',
|
|
});
|
|
|
|
// Test incompatible options.
|
|
const allOpts = {
|
|
group: 'modp5',
|
|
prime: Buffer.alloc(0),
|
|
primeLength: 1024,
|
|
generator: 2
|
|
};
|
|
const incompatible = [
|
|
['group', 'prime'],
|
|
['group', 'primeLength'],
|
|
['group', 'generator'],
|
|
['prime', 'primeLength'],
|
|
];
|
|
for (const [opt1, opt2] of incompatible) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync('dh', {
|
|
[opt1]: allOpts[opt1],
|
|
[opt2]: allOpts[opt2]
|
|
});
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_INCOMPATIBLE_OPTION_PAIR',
|
|
message: `Option "${opt1}" cannot be used in combination with option ` +
|
|
`"${opt2}"`
|
|
});
|
|
}
|
|
}
|
|
|
|
// Test invalid key encoding types.
|
|
{
|
|
// Invalid public key type.
|
|
for (const type of ['foo', 'pkcs8', 'sec1']) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: { type, format: 'pem' },
|
|
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.publicKeyEncoding.type' is invalid. " +
|
|
`Received ${inspect(type)}`
|
|
});
|
|
}
|
|
|
|
// Invalid hash value.
|
|
for (const hashValue of [123, true, {}, []]) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync('rsa-pss', {
|
|
modulusLength: 4096,
|
|
hashAlgorithm: hashValue
|
|
});
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.hashAlgorithm" property must be of type string.' +
|
|
common.invalidArgTypeHelper(hashValue)
|
|
});
|
|
}
|
|
|
|
// too long salt length
|
|
assert.throws(() => {
|
|
generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
saltLength: 2147483648,
|
|
hashAlgorithm: 'sha256',
|
|
mgf1HashAlgorithm: 'sha256'
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.saltLength" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
'Received 2147483648'
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
saltLength: -1,
|
|
hashAlgorithm: 'sha256',
|
|
mgf1HashAlgorithm: 'sha256'
|
|
}, common.mustNotCall());
|
|
}, {
|
|
name: 'RangeError',
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.saltLength" is out of range. ' +
|
|
'It must be >= 0 && <= 2147483647. ' +
|
|
'Received -1'
|
|
});
|
|
|
|
// Invalid private key type.
|
|
for (const type of ['foo', 'spki']) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync('rsa', {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: { type, format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_VALUE',
|
|
message: "The property 'options.privateKeyEncoding.type' is invalid. " +
|
|
`Received ${inspect(type)}`
|
|
});
|
|
}
|
|
|
|
// Key encoding doesn't match key type.
|
|
for (const type of ['dsa', 'ec']) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync(type, {
|
|
modulusLength: 4096,
|
|
namedCurve: 'P-256',
|
|
publicKeyEncoding: { type: 'pkcs1', format: 'pem' },
|
|
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'Error',
|
|
code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS',
|
|
message: 'The selected key encoding pkcs1 can only be used for RSA keys.'
|
|
});
|
|
|
|
assert.throws(() => {
|
|
generateKeyPairSync(type, {
|
|
modulusLength: 4096,
|
|
namedCurve: 'P-256',
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: { type: 'pkcs1', format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'Error',
|
|
code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS',
|
|
message: 'The selected key encoding pkcs1 can only be used for RSA keys.'
|
|
});
|
|
}
|
|
|
|
for (const type of ['rsa', 'dsa']) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync(type, {
|
|
modulusLength: 4096,
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: { type: 'sec1', format: 'pem' }
|
|
});
|
|
}, {
|
|
name: 'Error',
|
|
code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS',
|
|
message: 'The selected key encoding sec1 can only be used for EC keys.'
|
|
});
|
|
}
|
|
|
|
// Attempting to encrypt a DER-encoded, non-PKCS#8 key.
|
|
for (const type of ['pkcs1', 'sec1']) {
|
|
assert.throws(() => {
|
|
generateKeyPairSync(type === 'pkcs1' ? 'rsa' : 'ec', {
|
|
modulusLength: 4096,
|
|
namedCurve: 'P-256',
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: {
|
|
type,
|
|
format: 'der',
|
|
cipher: 'aes-128-cbc',
|
|
passphrase: 'hello'
|
|
}
|
|
});
|
|
}, {
|
|
name: 'Error',
|
|
code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS',
|
|
message: `The selected key encoding ${type} does not support encryption.`
|
|
});
|
|
}
|
|
}
|
|
|
|
{
|
|
// Test RSA-PSS.
|
|
assert.throws(
|
|
() => {
|
|
generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
saltLength: 16,
|
|
hashAlgorithm: 'sha256',
|
|
mgf1HashAlgorithm: undefined
|
|
});
|
|
},
|
|
{
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
}
|
|
);
|
|
|
|
for (const mgf1HashAlgorithm of [null, 0, false, {}, []]) {
|
|
assert.throws(
|
|
() => {
|
|
generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
saltLength: 16,
|
|
hashAlgorithm: 'sha256',
|
|
mgf1HashAlgorithm
|
|
}, common.mustNotCall());
|
|
},
|
|
{
|
|
name: 'TypeError',
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message:
|
|
'The "options.mgf1HashAlgorithm" property must be of type string.' +
|
|
common.invalidArgTypeHelper(mgf1HashAlgorithm)
|
|
|
|
}
|
|
);
|
|
}
|
|
|
|
assert.throws(() => generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
hashAlgorithm: 'sha2',
|
|
}, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_CRYPTO_INVALID_DIGEST',
|
|
message: 'Invalid digest: sha2'
|
|
});
|
|
|
|
assert.throws(() => generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
mgf1HashAlgorithm: 'sha2',
|
|
}, common.mustNotCall()), {
|
|
name: 'TypeError',
|
|
code: 'ERR_CRYPTO_INVALID_DIGEST',
|
|
message: 'Invalid MGF1 digest: sha2'
|
|
});
|
|
}
|
|
|
|
{
|
|
// This test makes sure deprecated and new options must
|
|
// be the same value.
|
|
|
|
assert.throws(() => generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
saltLength: 16,
|
|
mgf1Hash: 'sha256',
|
|
mgf1HashAlgorithm: 'sha1'
|
|
}, common.mustNotCall()), { code: 'ERR_INVALID_ARG_VALUE' });
|
|
|
|
assert.throws(() => generateKeyPair('rsa-pss', {
|
|
modulusLength: 512,
|
|
saltLength: 16,
|
|
hash: 'sha256',
|
|
hashAlgorithm: 'sha1'
|
|
}, common.mustNotCall()), { code: 'ERR_INVALID_ARG_VALUE' });
|
|
}
|