mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
7224940e54
To avoid timing out on ARM machines in the CI. PR-URL: https://github.com/nodejs/node/pull/49221 Refs: https://github.com/nodejs/node/issues/49202 Refs: https://github.com/nodejs/node/issues/41206 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');
|
|
|
|
|
|
// 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, common.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' });
|
|
}
|