#![allow(deprecated)] use digest::Digest; use dsa::{Components, KeySize, Signature, SigningKey}; use pkcs8::der::{Decode, Encode}; use rand::{CryptoRng, RngCore, SeedableRng}; use rand_chacha::ChaCha8Rng; use sha2::Sha256; use signature::{ hazmat::{PrehashSigner, PrehashVerifier}, DigestVerifier, RandomizedDigestSigner, Signer, Verifier, }; /// 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) const MESSAGE_SIGNATURE_CRATE_ASN1: &[u8] = &[ 0x30, 0x2C, 0x02, 0x14, 0x45, 0x1D, 0xE5, 0x76, 0x21, 0xD8, 0xFD, 0x76, 0xC1, 0x6F, 0x45, 0x4E, 0xDE, 0x5F, 0x09, 0x79, 0x76, 0x52, 0xF3, 0xA5, 0x02, 0x14, 0x53, 0x60, 0xE6, 0xB7, 0xF0, 0xCF, 0xAE, 0x49, 0xB1, 0x58, 0x5C, 0xCF, 0x5F, 0x3F, 0x94, 0x49, 0x21, 0xA0, 0xBF, 0xD2, ]; /// Message signed by OpenSSL using the keys generated by this CSPRNG /// /// This signature was generated using the SHA-256 digest const MESSAGE_SIGNATURE_OPENSSL_ASN1: &[u8] = &[ 0x30, 0x2C, 0x02, 0x14, 0x6D, 0xB3, 0x8E, 0xAF, 0x97, 0x13, 0x7E, 0x07, 0xFF, 0x24, 0xB8, 0x66, 0x97, 0x18, 0xE1, 0x6F, 0xD7, 0x9A, 0x28, 0x2D, 0x02, 0x14, 0x47, 0x8C, 0x0B, 0x96, 0x51, 0x08, 0x08, 0xC8, 0x34, 0x9D, 0x0D, 0x41, 0xC7, 0x73, 0x0F, 0xB5, 0x9C, 0xBB, 0x00, 0x34, ]; /// Get the seeded CSPRNG fn seeded_csprng() -> impl CryptoRng + RngCore { ChaCha8Rng::seed_from_u64(SEED) } /// Generate a DSA keypair using a seeded CSPRNG fn generate_deterministic_keypair() -> SigningKey { let mut rng = seeded_csprng(); let components = Components::generate(&mut rng, KeySize::DSA_1024_160); SigningKey::generate(&mut rng, components) } #[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_message() { let signing_key = generate_deterministic_keypair(); let generated_signature = signing_key.sign_digest_with_rng(&mut seeded_csprng(), Sha256::new().chain_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"); assert!(verifying_key .verify_digest(Sha256::new().chain_update(MESSAGE), &signature) .is_ok()); } #[test] fn signer_verifier_signature() { let signing_key = generate_deterministic_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(); }