1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
#![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();
}
|