mirror of https://github.com/nodejs/node.git
crypto: fix rsa-pss one-shot sign/verify error handling
fixes #39822 PR-URL: https://github.com/nodejs/node/pull/39830 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
e5670f4968
commit
b5816cddbc
|
@ -686,6 +686,7 @@ bool SignTraits::DeriveBits(
|
|||
nullptr,
|
||||
params.key.get())) {
|
||||
crypto::CheckThrow(env, SignBase::Error::kSignInit);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SignConfiguration::kVerify:
|
||||
|
@ -696,6 +697,7 @@ bool SignTraits::DeriveBits(
|
|||
nullptr,
|
||||
params.key.get())) {
|
||||
crypto::CheckThrow(env, SignBase::Error::kSignInit);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -713,6 +715,7 @@ bool SignTraits::DeriveBits(
|
|||
padding,
|
||||
salt_length)) {
|
||||
crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (params.mode) {
|
||||
|
|
|
@ -631,3 +631,114 @@ assert.throws(
|
|||
assert(stdout.includes('Verified OK'));
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
// Test RSA-PSS.
|
||||
{
|
||||
// This key pair does not restrict the message digest algorithm or salt
|
||||
// length.
|
||||
const publicPem = fixtures.readKey('rsa_pss_public_2048.pem');
|
||||
const privatePem = fixtures.readKey('rsa_pss_private_2048.pem');
|
||||
|
||||
const publicKey = crypto.createPublicKey(publicPem);
|
||||
const privateKey = crypto.createPrivateKey(privatePem);
|
||||
|
||||
for (const key of [privatePem, privateKey]) {
|
||||
// Any algorithm should work.
|
||||
for (const algo of ['sha1', 'sha256']) {
|
||||
// Any salt length should work.
|
||||
for (const saltLength of [undefined, 8, 10, 12, 16, 18, 20]) {
|
||||
const signature = crypto.sign(algo, 'foo', { key, saltLength });
|
||||
|
||||
for (const pkey of [key, publicKey, publicPem]) {
|
||||
const okay = crypto.verify(
|
||||
algo,
|
||||
'foo',
|
||||
{ key: pkey, saltLength },
|
||||
signature
|
||||
);
|
||||
|
||||
assert.ok(okay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// This key pair enforces sha256 as the message digest and the MGF1
|
||||
// message digest and a salt length of at least 16 bytes.
|
||||
const publicPem =
|
||||
fixtures.readKey('rsa_pss_public_2048_sha256_sha256_16.pem');
|
||||
const privatePem =
|
||||
fixtures.readKey('rsa_pss_private_2048_sha256_sha256_16.pem');
|
||||
|
||||
const publicKey = crypto.createPublicKey(publicPem);
|
||||
const privateKey = crypto.createPrivateKey(privatePem);
|
||||
|
||||
for (const key of [privatePem, privateKey]) {
|
||||
// Signing with anything other than sha256 should fail.
|
||||
assert.throws(() => {
|
||||
crypto.sign('sha1', 'foo', key);
|
||||
}, /digest not allowed/);
|
||||
|
||||
// Signing with salt lengths less than 16 bytes should fail.
|
||||
for (const saltLength of [8, 10, 12]) {
|
||||
assert.throws(() => {
|
||||
crypto.sign('sha256', 'foo', { key, saltLength });
|
||||
}, /pss saltlen too small/);
|
||||
}
|
||||
|
||||
// Signing with sha256 and appropriate salt lengths should work.
|
||||
for (const saltLength of [undefined, 16, 18, 20]) {
|
||||
const signature = crypto.sign('sha256', 'foo', { key, saltLength });
|
||||
|
||||
for (const pkey of [key, publicKey, publicPem]) {
|
||||
const okay = crypto.verify(
|
||||
'sha256',
|
||||
'foo',
|
||||
{ key: pkey, saltLength },
|
||||
signature
|
||||
);
|
||||
|
||||
assert.ok(okay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// This key enforces sha512 as the message digest and sha256 as the MGF1
|
||||
// message digest.
|
||||
const publicPem =
|
||||
fixtures.readKey('rsa_pss_public_2048_sha512_sha256_20.pem');
|
||||
const privatePem =
|
||||
fixtures.readKey('rsa_pss_private_2048_sha512_sha256_20.pem');
|
||||
|
||||
const publicKey = crypto.createPublicKey(publicPem);
|
||||
const privateKey = crypto.createPrivateKey(privatePem);
|
||||
|
||||
// Node.js usually uses the same hash function for the message and for MGF1.
|
||||
// However, when a different MGF1 message digest algorithm has been
|
||||
// specified as part of the key, it should automatically switch to that.
|
||||
// This behavior is required by sections 3.1 and 3.3 of RFC4055.
|
||||
for (const key of [privatePem, privateKey]) {
|
||||
// sha256 matches the MGF1 hash function and should be used internally,
|
||||
// but it should not be permitted as the main message digest algorithm.
|
||||
for (const algo of ['sha1', 'sha256']) {
|
||||
assert.throws(() => {
|
||||
crypto.sign(algo, 'foo', key);
|
||||
}, /digest not allowed/);
|
||||
}
|
||||
|
||||
// sha512 should produce a valid signature.
|
||||
const signature = crypto.sign('sha512', 'foo', key);
|
||||
|
||||
for (const pkey of [key, publicKey, publicPem]) {
|
||||
const okay = crypto.verify('sha512', 'foo', pkey, signature);
|
||||
|
||||
assert.ok(okay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue