mirror of
https://github.com/RustCrypto/signatures
synced 2026-06-21 13:45:42 +00:00
1b47ec5298
This renames the old `SigningKey::generate` to `try_generate_from_rng_with_components`, having the new one generate random `Components` with a 3072-bit modulus size, which is now the `Default` for `KeySize`.
156 lines
4.9 KiB
Rust
156 lines
4.9 KiB
Rust
#![cfg(feature = "hazmat")]
|
|
#![allow(deprecated)]
|
|
|
|
use digest::Digest;
|
|
use dsa::{Components, KeySize, Signature, SigningKey};
|
|
use getrandom::{SysRng, rand_core::UnwrapErr};
|
|
use hex_literal::hex;
|
|
use pkcs8::der::{Decode, Encode};
|
|
use sha2::Sha256;
|
|
use signature::{
|
|
DigestVerifier, RandomizedDigestSigner, Signer, Verifier,
|
|
hazmat::{PrehashSigner, PrehashVerifier},
|
|
};
|
|
|
|
/// Message to be signed/verified
|
|
const MESSAGE: &[u8] = b"test";
|
|
|
|
/// 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
|
|
///
|
|
/// This signature was generated using the SHA-256 digest
|
|
const MESSAGE_SIGNATURE_OPENSSL_ASN1: &[u8] = &hex!(
|
|
"302c 0214 3a2b 2250 3e2d 21b3 22a1 c834
|
|
1668 2c0c 98df 2dee 0214 501d 1ffb bbba
|
|
9925 a1d1 7bb8 c835 ca27 0931 ca6a"
|
|
);
|
|
|
|
/// Generate a random DSA keypair
|
|
fn generate_random_keypair() -> SigningKey {
|
|
let mut rng = UnwrapErr(SysRng);
|
|
let components =
|
|
Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_1024_160).unwrap();
|
|
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn decode_encode_signature() {
|
|
let signature_openssl =
|
|
Signature::from_der(MESSAGE_SIGNATURE_OPENSSL_ASN1).expect("Failed to decode signature");
|
|
let encoded_signature_openssl = signature_openssl
|
|
.to_der()
|
|
.expect("Failed to encode signature");
|
|
|
|
assert_eq!(MESSAGE_SIGNATURE_OPENSSL_ASN1, encoded_signature_openssl);
|
|
|
|
let signature_crate =
|
|
Signature::from_der(MESSAGE_SIGNATURE_CRATE_ASN1).expect("Failed to decode signature");
|
|
let encoded_signature_crate = signature_crate
|
|
.to_der()
|
|
.expect("Failed to encode signature");
|
|
|
|
assert_eq!(MESSAGE_SIGNATURE_CRATE_ASN1, encoded_signature_crate);
|
|
}
|
|
|
|
#[test]
|
|
fn sign_verify_message() {
|
|
let signing_key = generate_random_keypair();
|
|
let mut rng = UnwrapErr(SysRng);
|
|
let generated_signature =
|
|
signing_key.sign_digest_with_rng(&mut rng, |digest: &mut Sha256| digest.update(MESSAGE));
|
|
|
|
assert!(
|
|
signing_key
|
|
.verifying_key()
|
|
.verify_digest(
|
|
|digest: &mut Sha256| {
|
|
digest.update(MESSAGE);
|
|
Ok(())
|
|
},
|
|
&generated_signature
|
|
)
|
|
.is_ok()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn signer_verifier_signature() {
|
|
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.";
|
|
|
|
// construct signature manually and by `Signer` defaults. Ensure results are identical.
|
|
let manual_digest = Sha256::new_with_prefix(message).finalize();
|
|
let manual_signature = signing_key.sign_prehash(&manual_digest).unwrap();
|
|
let signer_signature = signing_key.sign(message);
|
|
verifying_key.verify(message, &manual_signature).unwrap();
|
|
verifying_key.verify(message, &signer_signature).unwrap();
|
|
assert_eq!(manual_signature, signer_signature);
|
|
|
|
// verify signature manually and by `Verifier` defaults. Ensure signatures can be applied interchangeably.
|
|
verifying_key
|
|
.verify_prehash(&manual_digest, &manual_signature)
|
|
.unwrap();
|
|
verifying_key
|
|
.verify_prehash(&manual_digest, &signer_signature)
|
|
.unwrap();
|
|
verifying_key.verify(message, &manual_signature).unwrap();
|
|
verifying_key.verify(message, &signer_signature).unwrap();
|
|
}
|
|
|
|
/// This test forces the r and s of the signature to a bit precision different to what would
|
|
/// otherwise be expected
|
|
#[test]
|
|
#[allow(clippy::slow_vector_initialization)]
|
|
fn verify_signature_precision() {
|
|
use der::{Sequence, asn1::Uint};
|
|
|
|
let signing_key = generate_random_keypair();
|
|
let verifying_key = signing_key.verifying_key();
|
|
|
|
#[derive(Sequence)]
|
|
struct MockSignature {
|
|
r: Uint,
|
|
s: Uint,
|
|
}
|
|
|
|
for value in &[
|
|
{
|
|
let mut value = vec![];
|
|
value.resize(512, 0);
|
|
value.push(1);
|
|
value
|
|
},
|
|
{
|
|
let mut value = vec![];
|
|
value.push(1);
|
|
value.resize(512, 0);
|
|
value
|
|
},
|
|
] {
|
|
let asn1 = MockSignature {
|
|
r: Uint::new(value).unwrap(),
|
|
s: Uint::new(value).unwrap(),
|
|
}
|
|
.to_der()
|
|
.expect("Failed to serialize signature");
|
|
|
|
let signature = Signature::from_der(&asn1)
|
|
.expect("Failed to parse ASN.1 representation of the test signature");
|
|
|
|
let _ = verifying_key.verify_digest(
|
|
|digest: &mut Sha256| {
|
|
digest.update(MESSAGE);
|
|
Ok(())
|
|
},
|
|
&signature,
|
|
);
|
|
}
|
|
}
|