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>
587 lines
18 KiB
JavaScript
587 lines
18 KiB
JavaScript
'use strict';
|
|
const common = require('../common');
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const assert = require('assert');
|
|
const crypto = require('crypto');
|
|
|
|
const constants = crypto.constants;
|
|
|
|
const fixtures = require('../common/fixtures');
|
|
const {
|
|
hasOpenSSL,
|
|
hasFIPS,
|
|
isBoringSSL,
|
|
} = require('../common/crypto');
|
|
const fips3 = hasFIPS(3);
|
|
const fips35 = hasFIPS(3, 5);
|
|
const fips4 = hasFIPS(4);
|
|
const wrongPassphrase = 'wrong-password';
|
|
|
|
// Test certificates
|
|
const certPem = fixtures.readKey('rsa_cert.crt');
|
|
const keyPem = fixtures.readKey('rsa_private.pem');
|
|
const rsaKeySize = 2048;
|
|
const rsaPubPem = fixtures.readKey('rsa_public.pem', 'ascii');
|
|
const rsaKeyPem = fixtures.readKey('rsa_private.pem', 'ascii');
|
|
// Fixed ciphertexts keep wrong passwords from occasionally producing valid
|
|
// padding and a decoder error instead of the expected bad decrypt.
|
|
const rsaKeyPemEncrypted = fixtures.readKey(
|
|
'rsa_private_encrypted.pem', 'ascii');
|
|
const dsaPubPem = fixtures.readKey('dsa_public.pem', 'ascii');
|
|
const dsaKeyPem = fixtures.readKey('dsa_private.pem', 'ascii');
|
|
const dsaKeyPemEncrypted = fixtures.readKey(
|
|
'dsa_private_encrypted.pem', 'ascii');
|
|
const rsaPkcs8KeyPem = fixtures.readKey('rsa_private_pkcs8.pem');
|
|
const dsaPkcs8KeyPem = fixtures.readKey('dsa_private_pkcs8.pem');
|
|
|
|
const ec = new TextEncoder();
|
|
|
|
const decryptError = fips4 ?
|
|
{ code: 'ERR_OSSL_BAD_DECRYPT' } :
|
|
isBoringSSL ? {
|
|
message: 'error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT',
|
|
code: 'ERR_OSSL_BAD_DECRYPT',
|
|
reason: 'BAD_DECRYPT',
|
|
function: 'OPENSSL_internal',
|
|
library: 'Cipher functions',
|
|
} : {
|
|
message: 'error:1C800064:Provider routines::bad decrypt',
|
|
};
|
|
|
|
const decryptPrivateKeyError = fips4 ? {
|
|
code: 'ERR_OSSL_BAD_DECRYPT',
|
|
} : isBoringSSL ? {
|
|
message: 'error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT',
|
|
} : {
|
|
message: 'error:1C800064:Provider routines::bad decrypt',
|
|
};
|
|
|
|
function getBufferCopy(buf) {
|
|
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
}
|
|
|
|
// Test RSA encryption/decryption
|
|
{
|
|
const input = 'I AM THE WALRUS';
|
|
const bufferToEncrypt = Buffer.from(input);
|
|
const bufferPassword = Buffer.from('password');
|
|
|
|
let encryptedBuffer = crypto.publicEncrypt(rsaPubPem, bufferToEncrypt);
|
|
|
|
// Test other input types
|
|
let otherEncrypted;
|
|
{
|
|
const ab = getBufferCopy(ec.encode(rsaPubPem));
|
|
const ab2enc = getBufferCopy(bufferToEncrypt);
|
|
|
|
crypto.publicEncrypt(ab, ab2enc);
|
|
crypto.publicEncrypt(new Uint8Array(ab), new Uint8Array(ab2enc));
|
|
crypto.publicEncrypt(new DataView(ab), new DataView(ab2enc));
|
|
otherEncrypted = crypto.publicEncrypt({
|
|
key: Buffer.from(ab).toString('hex'),
|
|
encoding: 'hex'
|
|
}, Buffer.from(ab2enc).toString('hex'));
|
|
}
|
|
|
|
let decryptedBuffer = crypto.privateDecrypt(rsaKeyPem, encryptedBuffer);
|
|
const otherDecrypted = crypto.privateDecrypt(rsaKeyPem, otherEncrypted);
|
|
assert.strictEqual(decryptedBuffer.toString(), input);
|
|
assert.strictEqual(otherDecrypted.toString(), input);
|
|
|
|
decryptedBuffer = crypto.privateDecrypt(rsaPkcs8KeyPem, encryptedBuffer);
|
|
assert.strictEqual(decryptedBuffer.toString(), input);
|
|
|
|
let decryptedBufferWithPassword = crypto.privateDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: 'password'
|
|
}, encryptedBuffer);
|
|
|
|
const otherDecryptedBufferWithPassword = crypto.privateDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: ec.encode('password')
|
|
}, encryptedBuffer);
|
|
|
|
assert.strictEqual(
|
|
otherDecryptedBufferWithPassword.toString(),
|
|
decryptedBufferWithPassword.toString());
|
|
|
|
decryptedBufferWithPassword = crypto.privateDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: 'password'
|
|
}, encryptedBuffer);
|
|
|
|
assert.strictEqual(decryptedBufferWithPassword.toString(), input);
|
|
|
|
encryptedBuffer = crypto.publicEncrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: 'password'
|
|
}, bufferToEncrypt);
|
|
|
|
decryptedBufferWithPassword = crypto.privateDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: 'password'
|
|
}, encryptedBuffer);
|
|
assert.strictEqual(decryptedBufferWithPassword.toString(), input);
|
|
|
|
encryptedBuffer = crypto.privateEncrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, bufferToEncrypt);
|
|
|
|
decryptedBufferWithPassword = crypto.publicDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, encryptedBuffer);
|
|
assert.strictEqual(decryptedBufferWithPassword.toString(), input);
|
|
|
|
// Now with explicit RSA_PKCS1_PADDING.
|
|
encryptedBuffer = crypto.privateEncrypt({
|
|
padding: crypto.constants.RSA_PKCS1_PADDING,
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, bufferToEncrypt);
|
|
|
|
decryptedBufferWithPassword = crypto.publicDecrypt({
|
|
padding: crypto.constants.RSA_PKCS1_PADDING,
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, encryptedBuffer);
|
|
assert.strictEqual(decryptedBufferWithPassword.toString(), input);
|
|
|
|
// Omitting padding should be okay because RSA_PKCS1_PADDING is the default.
|
|
decryptedBufferWithPassword = crypto.publicDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, encryptedBuffer);
|
|
assert.strictEqual(decryptedBufferWithPassword.toString(), input);
|
|
|
|
// BoringSSL does not apply OpenSSL's rsa_check_padding validation here.
|
|
if (isBoringSSL) {
|
|
{
|
|
const plaintext = 'x'.repeat(rsaKeySize / 8);
|
|
encryptedBuffer = crypto.privateEncrypt({
|
|
padding: crypto.constants.RSA_NO_PADDING,
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, Buffer.from(plaintext));
|
|
|
|
decryptedBufferWithPassword = crypto.publicDecrypt({
|
|
padding: crypto.constants.RSA_NO_PADDING,
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: bufferPassword
|
|
}, encryptedBuffer);
|
|
assert.strictEqual(decryptedBufferWithPassword.toString(), plaintext);
|
|
}
|
|
}
|
|
|
|
encryptedBuffer = crypto.publicEncrypt(certPem, bufferToEncrypt);
|
|
|
|
decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer);
|
|
assert.strictEqual(decryptedBuffer.toString(), input);
|
|
|
|
encryptedBuffer = crypto.publicEncrypt(keyPem, bufferToEncrypt);
|
|
|
|
decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer);
|
|
assert.strictEqual(decryptedBuffer.toString(), input);
|
|
|
|
encryptedBuffer = crypto.privateEncrypt(keyPem, bufferToEncrypt);
|
|
|
|
decryptedBuffer = crypto.publicDecrypt(keyPem, encryptedBuffer);
|
|
assert.strictEqual(decryptedBuffer.toString(), input);
|
|
|
|
assert.throws(() => {
|
|
crypto.privateDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: wrongPassphrase
|
|
}, bufferToEncrypt);
|
|
}, decryptError);
|
|
|
|
assert.throws(() => {
|
|
crypto.publicEncrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: wrongPassphrase
|
|
}, encryptedBuffer);
|
|
}, decryptError);
|
|
|
|
encryptedBuffer = crypto.privateEncrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: Buffer.from('password')
|
|
}, bufferToEncrypt);
|
|
|
|
assert.throws(() => {
|
|
crypto.publicDecrypt({
|
|
key: rsaKeyPemEncrypted,
|
|
passphrase: Buffer.from(wrongPassphrase)
|
|
}, encryptedBuffer);
|
|
}, decryptError);
|
|
}
|
|
|
|
function test_rsa(padding, encryptOaepHash, decryptOaepHash) {
|
|
const size = (padding === 'RSA_NO_PADDING') ? rsaKeySize / 8 : 32;
|
|
const input = Buffer.allocUnsafe(size);
|
|
for (let i = 0; i < input.length; i++)
|
|
input[i] = (i * 7 + 11) & 0xff;
|
|
const bufferToEncrypt = Buffer.from(input);
|
|
|
|
padding = constants[padding];
|
|
|
|
const encryptedBuffer = crypto.publicEncrypt({
|
|
key: rsaPubPem,
|
|
padding: padding,
|
|
oaepHash: encryptOaepHash
|
|
}, bufferToEncrypt);
|
|
|
|
|
|
if (padding === constants.RSA_PKCS1_PADDING) {
|
|
if (!process.config.variables.node_shared_openssl) {
|
|
// TODO(richardlau) remove check and else branch after deps/openssl
|
|
// is upgraded.
|
|
if (hasOpenSSL(3, 2)) {
|
|
let decryptedBuffer = crypto.privateDecrypt({
|
|
key: rsaKeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
assert.deepStrictEqual(decryptedBuffer, input);
|
|
|
|
decryptedBuffer = crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
assert.deepStrictEqual(decryptedBuffer, input);
|
|
} else {
|
|
assert.throws(() => {
|
|
crypto.privateDecrypt({
|
|
key: rsaKeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
}, { code: 'ERR_INVALID_ARG_VALUE' });
|
|
assert.throws(() => {
|
|
crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
}, { code: 'ERR_INVALID_ARG_VALUE' });
|
|
}
|
|
} else {
|
|
// The version of a linked against OpenSSL. May
|
|
// or may not support implicit rejection. Figuring
|
|
// this out in the test is not feasible but we
|
|
// require that it pass based on one of the two
|
|
// cases of supporting it or not.
|
|
try {
|
|
// The expected exceptions should be thrown if implicit rejection
|
|
// is not supported
|
|
assert.throws(() => {
|
|
crypto.privateDecrypt({
|
|
key: rsaKeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
}, { code: 'ERR_INVALID_ARG_VALUE' });
|
|
assert.throws(() => {
|
|
crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
}, { code: 'ERR_INVALID_ARG_VALUE' });
|
|
} catch (e) {
|
|
if (e.toString() ===
|
|
'AssertionError [ERR_ASSERTION]: Missing expected exception.') {
|
|
// Implicit rejection must be supported since
|
|
// we did not get the exceptions that are thrown
|
|
// when it is not, we should be able to decrypt
|
|
let decryptedBuffer = crypto.privateDecrypt({
|
|
key: rsaKeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
assert.deepStrictEqual(decryptedBuffer, input);
|
|
|
|
decryptedBuffer = crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
assert.deepStrictEqual(decryptedBuffer, input);
|
|
} else {
|
|
// There was an exception but it is not the one we expect if implicit
|
|
// rejection is not supported so there was some other failure,
|
|
// re-throw it so the test fails
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
let decryptedBuffer = crypto.privateDecrypt({
|
|
key: rsaKeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
assert.deepStrictEqual(decryptedBuffer, input);
|
|
|
|
decryptedBuffer = crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
padding: padding,
|
|
oaepHash: decryptOaepHash
|
|
}, encryptedBuffer);
|
|
assert.deepStrictEqual(decryptedBuffer, input);
|
|
}
|
|
}
|
|
|
|
test_rsa('RSA_NO_PADDING');
|
|
test_rsa('RSA_PKCS1_OAEP_PADDING');
|
|
|
|
if (!isBoringSSL) {
|
|
test_rsa('RSA_PKCS1_PADDING');
|
|
} else {
|
|
common.printSkipMessage('Skipping unsupported RSA_PKCS1_PADDING test case');
|
|
}
|
|
|
|
// Test OAEP with different hash functions.
|
|
test_rsa('RSA_PKCS1_OAEP_PADDING', undefined, 'sha1');
|
|
test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha1', undefined);
|
|
test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha256', 'sha256');
|
|
test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha512', 'sha512');
|
|
assert.throws(() => {
|
|
test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha256', 'sha512');
|
|
}, fips35 ? {
|
|
code: 'ERR_OSSL_EVP_PROVIDER_ASYM_CIPHER_FAILURE',
|
|
} : fips3 ? {
|
|
message: 'error:00000000:lib(0)::reason(0)',
|
|
} : {
|
|
code: 'ERR_OSSL_RSA_OAEP_DECODING_ERROR',
|
|
});
|
|
|
|
// The following RSA-OAEP test cases were created using the WebCrypto API to
|
|
// ensure compatibility when using non-SHA1 hash functions.
|
|
{
|
|
const { decryptionTests } =
|
|
JSON.parse(fixtures.readSync('rsa-oaep-test-vectors.js', 'utf8'));
|
|
|
|
for (const { ct, oaepHash, oaepLabel } of decryptionTests) {
|
|
const label = oaepLabel ? Buffer.from(oaepLabel, 'hex') : undefined;
|
|
const copiedLabel = oaepLabel ? getBufferCopy(label) : undefined;
|
|
|
|
const decrypted = crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
oaepHash,
|
|
oaepLabel: oaepLabel ? label : undefined
|
|
}, Buffer.from(ct, 'hex'));
|
|
|
|
assert.strictEqual(decrypted.toString('utf8'), 'Hello Node.js');
|
|
|
|
const otherDecrypted = crypto.privateDecrypt({
|
|
key: rsaPkcs8KeyPem,
|
|
oaepHash,
|
|
oaepLabel: copiedLabel
|
|
}, Buffer.from(ct, 'hex'));
|
|
|
|
assert.strictEqual(otherDecrypted.toString('utf8'), 'Hello Node.js');
|
|
}
|
|
}
|
|
|
|
// Test invalid oaepHash and oaepLabel options.
|
|
for (const fn of [crypto.publicEncrypt, crypto.privateDecrypt]) {
|
|
assert.throws(() => {
|
|
fn({
|
|
key: rsaPubPem,
|
|
oaepHash: 'Hello world'
|
|
}, Buffer.alloc(10));
|
|
}, {
|
|
code: 'ERR_OSSL_EVP_INVALID_DIGEST'
|
|
});
|
|
|
|
for (const oaepHash of [0, false, null, Symbol(), () => {}]) {
|
|
assert.throws(() => {
|
|
fn({
|
|
key: rsaPubPem,
|
|
oaepHash
|
|
}, Buffer.alloc(10));
|
|
}, {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
}
|
|
|
|
for (const oaepLabel of [0, false, null, Symbol(), () => {}, {}]) {
|
|
assert.throws(() => {
|
|
fn({
|
|
key: rsaPubPem,
|
|
oaepLabel
|
|
}, Buffer.alloc(10));
|
|
}, {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Test RSA key signing/verification
|
|
const rsaDigest = fips3 ? 'SHA256' : 'SHA1';
|
|
let rsaSign = crypto.createSign(rsaDigest);
|
|
let rsaVerify = crypto.createVerify(rsaDigest);
|
|
assert.ok(rsaSign);
|
|
assert.ok(rsaVerify);
|
|
|
|
const expectedSignature = fixtures.readKey(
|
|
'rsa_public_sha1_signature_signedby_rsa_private_pkcs8.sha1',
|
|
'hex'
|
|
);
|
|
|
|
rsaSign.update(rsaPubPem);
|
|
let rsaSignature = rsaSign.sign(rsaKeyPem, 'hex');
|
|
if (!fips3)
|
|
assert.strictEqual(rsaSignature, expectedSignature);
|
|
|
|
rsaVerify.update(rsaPubPem);
|
|
assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
|
|
|
|
// Test RSA PKCS#8 key signing/verification
|
|
rsaSign = crypto.createSign(rsaDigest);
|
|
rsaSign.update(rsaPubPem);
|
|
rsaSignature = rsaSign.sign(rsaPkcs8KeyPem, 'hex');
|
|
if (!fips3)
|
|
assert.strictEqual(rsaSignature, expectedSignature);
|
|
|
|
rsaVerify = crypto.createVerify(rsaDigest);
|
|
rsaVerify.update(rsaPubPem);
|
|
assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
|
|
|
|
// Test RSA key signing/verification with encrypted key
|
|
rsaSign = crypto.createSign(rsaDigest);
|
|
rsaSign.update(rsaPubPem);
|
|
const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'password' };
|
|
rsaSignature = rsaSign.sign(signOptions, 'hex');
|
|
if (!fips3)
|
|
assert.strictEqual(rsaSignature, expectedSignature);
|
|
|
|
rsaVerify = crypto.createVerify(rsaDigest);
|
|
rsaVerify.update(rsaPubPem);
|
|
assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
|
|
|
|
rsaSign = crypto.createSign(rsaDigest);
|
|
rsaSign.update(rsaPubPem);
|
|
assert.throws(() => {
|
|
const signOptions = { key: rsaKeyPemEncrypted, passphrase: wrongPassphrase };
|
|
rsaSign.sign(signOptions, 'hex');
|
|
}, decryptPrivateKeyError);
|
|
|
|
//
|
|
// Test RSA signing and verification
|
|
//
|
|
{
|
|
const privateKey = fixtures.readKey('rsa_private_b.pem');
|
|
const publicKey = fixtures.readKey('rsa_public_b.pem');
|
|
|
|
const input = 'I AM THE WALRUS';
|
|
|
|
const signature = fixtures.readKey(
|
|
'I_AM_THE_WALRUS_sha256_signature_signedby_rsa_private_b.sha256',
|
|
'hex'
|
|
);
|
|
|
|
const sign = crypto.createSign('SHA256');
|
|
sign.update(input);
|
|
|
|
const output = sign.sign(privateKey, 'hex');
|
|
assert.strictEqual(output, signature);
|
|
|
|
const verify = crypto.createVerify('SHA256');
|
|
verify.update(input);
|
|
|
|
assert.strictEqual(verify.verify(publicKey, signature, 'hex'), true);
|
|
|
|
// Test the legacy signature algorithm name.
|
|
const sign2 = crypto.createSign('RSA-SHA256');
|
|
sign2.update(input);
|
|
|
|
const output2 = sign2.sign(privateKey, 'hex');
|
|
assert.strictEqual(output2, signature);
|
|
|
|
const verify2 = crypto.createVerify('SHA256');
|
|
verify2.update(input);
|
|
|
|
assert.strictEqual(verify2.verify(publicKey, signature, 'hex'), true);
|
|
}
|
|
|
|
|
|
//
|
|
// Test DSA signing and verification
|
|
//
|
|
if (!isBoringSSL) {
|
|
const input = 'I AM THE WALRUS';
|
|
|
|
// DSA signatures vary across runs so there is no static string to verify
|
|
// against.
|
|
const dsaDigest = fips3 ? 'SHA256' : 'SHA1';
|
|
const sign = crypto.createSign(dsaDigest);
|
|
sign.update(input);
|
|
const signature = sign.sign(dsaKeyPem, 'hex');
|
|
|
|
const verify = crypto.createVerify(dsaDigest);
|
|
verify.update(input);
|
|
|
|
assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true);
|
|
|
|
} else {
|
|
common.printSkipMessage('Skipping unsupported DSA test case');
|
|
}
|
|
|
|
|
|
//
|
|
// Test DSA signing and verification with PKCS#8 private key
|
|
//
|
|
if (!isBoringSSL) {
|
|
const input = 'I AM THE WALRUS';
|
|
|
|
// DSA signatures vary across runs so there is no static string to verify
|
|
// against.
|
|
const dsaDigest = fips3 ? 'SHA256' : 'SHA1';
|
|
const sign = crypto.createSign(dsaDigest);
|
|
sign.update(input);
|
|
const signature = sign.sign(dsaPkcs8KeyPem, 'hex');
|
|
|
|
const verify = crypto.createVerify(dsaDigest);
|
|
verify.update(input);
|
|
|
|
assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true);
|
|
} else {
|
|
common.printSkipMessage('Skipping unsupported DSA test case');
|
|
}
|
|
|
|
|
|
//
|
|
// Test DSA signing and verification with encrypted key
|
|
//
|
|
const input = 'I AM THE WALRUS';
|
|
|
|
{
|
|
const sign = crypto.createSign(fips3 ? 'SHA256' : 'SHA1');
|
|
sign.update(input);
|
|
assert.throws(() => {
|
|
sign.sign({ key: dsaKeyPemEncrypted, passphrase: wrongPassphrase }, 'hex');
|
|
}, decryptPrivateKeyError);
|
|
}
|
|
|
|
if (!isBoringSSL) {
|
|
// DSA signatures vary across runs so there is no static string to verify
|
|
// against.
|
|
const dsaDigest = fips3 ? 'SHA256' : 'SHA1';
|
|
const sign = crypto.createSign(dsaDigest);
|
|
sign.update(input);
|
|
const signOptions = { key: dsaKeyPemEncrypted, passphrase: 'password' };
|
|
const signature = sign.sign(signOptions, 'hex');
|
|
|
|
const verify = crypto.createVerify(dsaDigest);
|
|
verify.update(input);
|
|
|
|
assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true);
|
|
} else {
|
|
common.printSkipMessage('Skipping unsupported DSA test case');
|
|
}
|