dsa: decouple precise RNG state from tests (#1139)

The `signature` test was too tightly coupled with the precise RNG
output, in effect not just testing the DSA signature/verification logic
but also testing that the exact bit sequence was produced by the
dependent crate.

We already have tests against deterministic keys and signatures at
`tests/deterministic.rs`, so modify `tests/signature.rs` to instead
generate a random keypair using the system RNG, then generate a
signature with that keypair, and then verify that signature.

The existing hard-coded signatures have been left in place as they are
used to test PKCS decoding and encoding.
This commit is contained in:
Steven Dee
2026-01-05 19:33:18 -05:00
committed by GitHub
parent ab591d8a12
commit 4112075105
3 changed files with 18 additions and 41 deletions
Generated
+1
View File
@@ -371,6 +371,7 @@ dependencies = [
"hex-literal",
"pkcs8",
"proptest",
"rand_core 0.10.0-rc-3",
"rfc6979",
"sha1",
"sha2",
+1
View File
@@ -37,6 +37,7 @@ proptest = "1"
getrandom = { version = "0.4.0-rc.0", features = ["sys_rng"] }
sha1 = "0.11.0-rc.2"
der = { version = "0.8.0-rc.10", features = ["derive"] }
rand_core = "0.10.0-rc-3"
[features]
default = ["pkcs8"]
+16 -41
View File
@@ -1,34 +1,28 @@
#![cfg(feature = "hazmat")]
#![allow(deprecated)]
use chacha20::{ChaCha8Rng, rand_core::SeedableRng};
use digest::Digest;
use dsa::{Components, KeySize, Signature, SigningKey};
use getrandom::rand_core::CryptoRng;
use hex_literal::hex;
use pkcs8::der::{Decode, Encode};
use rand_core::TryRngCore;
use sha2::Sha256;
use signature::{
DigestVerifier, RandomizedDigestSigner, Signer, Verifier,
hazmat::{PrehashSigner, PrehashVerifier},
};
/// Seed used for the ChaCha8 RNG
const SEED: u64 = 0x2103_1949;
/// Message to be signed/verified
const MESSAGE: &[u8] = b"test";
/// Message signed by this crate using the keys generated by this CSPRNG
///
/// This signature was generated using the keys generated by this CSPRNG (the per-message `k` component was also generated using the CSPRNG)
/// Message signed by this crate
const MESSAGE_SIGNATURE_CRATE_ASN1: &[u8] = &[
0x30, 0x2c, 0x2, 0x14, 0x4e, 0x12, 0x27, 0x75, 0x18, 0xf6, 0x40, 0xe3, 0x3a, 0xdb, 0x80, 0x6d,
0xe7, 0x98, 0xd3, 0xa3, 0x40, 0xf5, 0x9d, 0xf, 0x2, 0x14, 0x17, 0x78, 0x1e, 0xc8, 0x53, 0x58,
0x91, 0xe0, 0x3f, 0x2d, 0x36, 0x27, 0x36, 0x6b, 0xac, 0x8e, 0xd7, 0xf9, 0xa4, 0xcf,
];
/// Message signed by OpenSSL using the keys generated by this CSPRNG
/// Message signed by OpenSSL
///
/// This signature was generated using the SHA-256 digest
const MESSAGE_SIGNATURE_OPENSSL_ASN1: &[u8] = &hex!(
@@ -37,14 +31,9 @@ const MESSAGE_SIGNATURE_OPENSSL_ASN1: &[u8] = &hex!(
9925 a1d1 7bb8 c835 ca27 0931 ca6a"
);
/// Get the seeded CSPRNG
fn seeded_csprng() -> impl CryptoRng {
ChaCha8Rng::seed_from_u64(SEED)
}
/// Generate a DSA keypair using a seeded CSPRNG
fn generate_deterministic_keypair() -> SigningKey {
let mut rng = seeded_csprng();
/// Generate a random DSA keypair
fn generate_random_keypair() -> SigningKey {
let mut rng = getrandom::SysRng.unwrap_err();
let components = Components::generate(&mut rng, KeySize::DSA_1024_160);
SigningKey::generate(&mut rng, components)
}
@@ -69,35 +58,21 @@ fn decode_encode_signature() {
}
#[test]
fn sign_message() {
let signing_key = generate_deterministic_keypair();
let generated_signature = signing_key
.sign_digest_with_rng(&mut seeded_csprng(), |digest: &mut Sha256| {
digest.update(MESSAGE)
});
let expected_signature =
Signature::from_der(MESSAGE_SIGNATURE_CRATE_ASN1).expect("Failed to decode signature");
assert_eq!(generated_signature, expected_signature);
}
#[test]
fn verify_signature() {
let signing_key = generate_deterministic_keypair();
let verifying_key = signing_key.verifying_key();
let signature = Signature::from_der(MESSAGE_SIGNATURE_OPENSSL_ASN1)
.expect("Failed to parse ASN.1 representation of the test signature");
fn sign_verify_message() {
let signing_key = generate_random_keypair();
let mut rng = getrandom::SysRng.unwrap_err();
let generated_signature =
signing_key.sign_digest_with_rng(&mut rng, |digest: &mut Sha256| digest.update(MESSAGE));
assert!(
verifying_key
signing_key
.verifying_key()
.verify_digest(
|digest: &mut Sha256| {
digest.update(MESSAGE);
Ok(())
},
&signature
&generated_signature
)
.is_ok()
);
@@ -105,7 +80,7 @@ fn verify_signature() {
#[test]
fn signer_verifier_signature() {
let signing_key = generate_deterministic_keypair();
let signing_key = generate_random_keypair();
let verifying_key = signing_key.verifying_key();
let message = b"Hello world! This is the message signed as part of the testing process.";
@@ -135,7 +110,7 @@ fn signer_verifier_signature() {
fn verify_signature_precision() {
use der::{Sequence, asn1::Uint};
let signing_key = generate_deterministic_keypair();
let signing_key = generate_random_keypair();
let verifying_key = signing_key.verifying_key();
#[derive(Sequence)]