mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
Delete test-crypto-ecb.js, which can no longer run anywhere: Blowfish is available only from OpenSSL's legacy provider and is absent from BoringSSL. The addon and cctest version guards become OPENSSL_IS_BORINGSSL checks. Remove legacy digest-alias coverage and unreachable OpenSSL 1.x branches. JavaScript test and benchmark gates, skip reasons, and TLS error expectations that distinguished OpenSSL 1.x from provider-backed OpenSSL now distinguish BoringSSL, including PKCS12 parsing, named DH groups, private-key serialization, RSA-PSS parameters, consolidated provider caches, FIPS availability, and empty KMAC output. Keep the CCM alternate finalization error only for BoringSSL. Provider-only test skips use version-neutral terminology or state the actual minimum OpenSSL version. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: https://github.com/nodejs/node/pull/64777 Fixes: https://github.com/nodejs/node/issues/56733 Refs: https://github.com/nodejs/node/pull/64211 Refs: https://github.com/nodejs/node/pull/63966 Refs: https://github.com/nodejs/node/pull/53329 Refs: https://github.com/nodejs/node/pull/48950 Refs: https://github.com/nodejs/node/issues/45465 Refs: https://github.com/nodejs/node/issues/42827 Refs: https://github.com/nodejs/node/issues/47076 Refs: https://github.com/nodejs/node/pull/62862 Refs: https://github.com/nodejs/node/pull/38512 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
114 lines
3.4 KiB
JavaScript
114 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const { hasFIPS, isBoringSSL } = require('../common/crypto');
|
|
if (isBoringSSL)
|
|
common.skip('OpenSSL providers are required');
|
|
|
|
const assert = require('assert');
|
|
const {
|
|
createPrivateKey,
|
|
createPublicKey,
|
|
generateKeyPair,
|
|
generateKeyPairSync,
|
|
getCiphers,
|
|
sign,
|
|
verify,
|
|
} = require('crypto');
|
|
|
|
// Resolve an AES-256-CBC provider alias and retain the fetched cipher while
|
|
// encoding private keys and running asynchronous key generation jobs.
|
|
const cipher = '2.16.840.1.101.3.4.1.42';
|
|
const passphrase = 'provider cipher passphrase';
|
|
const keyOptions = { namedCurve: 'prime256v1' };
|
|
const { publicKey, privateKey } = generateKeyPairSync('ec', keyOptions);
|
|
const data = Buffer.from('encrypted private key');
|
|
|
|
function checkPrivateKey(encoded, format, type, expectedPublicKey) {
|
|
const decrypted = createPrivateKey({
|
|
key: encoded,
|
|
format,
|
|
type,
|
|
passphrase,
|
|
});
|
|
assert(createPublicKey(decrypted).equals(expectedPublicKey));
|
|
const signature = sign('sha256', data, decrypted);
|
|
assert(verify('sha256', data, expectedPublicKey, signature));
|
|
}
|
|
|
|
for (const format of ['pem', 'der']) {
|
|
const privateKeyEncoding = {
|
|
format,
|
|
type: 'pkcs8',
|
|
cipher,
|
|
passphrase,
|
|
};
|
|
|
|
const exported = privateKey.export(privateKeyEncoding);
|
|
if (format === 'pem')
|
|
assert.match(exported, /^-----BEGIN ENCRYPTED PRIVATE KEY-----/);
|
|
checkPrivateKey(exported, format, 'pkcs8', publicKey);
|
|
|
|
const generated = generateKeyPairSync('ec', {
|
|
...keyOptions,
|
|
privateKeyEncoding,
|
|
});
|
|
checkPrivateKey(generated.privateKey, format, 'pkcs8', generated.publicKey);
|
|
|
|
// Async jobs copy the encoding configuration. Its fetched cipher must remain
|
|
// valid after the configuration used to create the job has been destroyed.
|
|
generateKeyPair('ec', {
|
|
...keyOptions,
|
|
privateKeyEncoding,
|
|
}, common.mustSucceed((generatedPublicKey, generatedPrivateKey) => {
|
|
checkPrivateKey(generatedPrivateKey, format, 'pkcs8', generatedPublicKey);
|
|
}));
|
|
}
|
|
|
|
// Provider lookup must preserve the restrictions of each key format.
|
|
const sec1 = { format: 'pem', type: 'sec1', cipher, passphrase };
|
|
// Traditional PEM encryption uses MD5 to derive its key.
|
|
if (!hasFIPS())
|
|
checkPrivateKey(privateKey.export(sec1), 'pem', 'sec1', publicKey);
|
|
assert.throws(() => privateKey.export({ ...sec1, format: 'der' }), {
|
|
code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS',
|
|
});
|
|
|
|
const unknownCipher = {
|
|
format: 'pem',
|
|
type: 'pkcs8',
|
|
cipher: 'unknown-private-key-cipher',
|
|
passphrase,
|
|
};
|
|
const unknownCipherError = {
|
|
code: 'ERR_CRYPTO_UNKNOWN_CIPHER',
|
|
message: 'Unknown cipher',
|
|
};
|
|
assert.throws(() => privateKey.export(unknownCipher), unknownCipherError);
|
|
assert.throws(() => generateKeyPairSync('ec', {
|
|
...keyOptions,
|
|
privateKeyEncoding: unknownCipher,
|
|
}), unknownCipherError);
|
|
assert.throws(() => generateKeyPair('ec', {
|
|
...keyOptions,
|
|
privateKeyEncoding: unknownCipher,
|
|
}, common.mustNotCall()), unknownCipherError);
|
|
|
|
// Provider-only ciphers must reach the serializer, which still rejects ciphers
|
|
// without an ASN.1 identifier when writing PKCS8.
|
|
if (getCiphers().includes('aes-128-cbc-cts')) {
|
|
for (const format of ['pem', 'der']) {
|
|
assert.throws(() => privateKey.export({
|
|
format,
|
|
type: 'pkcs8',
|
|
cipher: 'aes-128-cbc-cts',
|
|
passphrase,
|
|
}), {
|
|
code: 'ERR_OSSL_ASN1_CIPHER_HAS_NO_OBJECT_IDENTIFIER',
|
|
});
|
|
}
|
|
}
|