Something went wrong. Try again.
Typelevel cryptographic algo tracking crates.io/crates/evidence
typelevel cryptography util
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305//! Property-based tests for Signed and Verified.
#![cfg(feature = "ed25519")]
use bolero::check;use evidence::{ codec::Identity, signature::ed25519::Ed25519, signed::{Signed, SignedUnchecked}, verified::{Verified, VerifiedUnchecked},};
/// Helper to create a signing key from seed bytes.fn signing_key_from_seed(seed: [u8; 32]) -> ed25519_dalek::SigningKey { ed25519_dalek::SigningKey::from_bytes(&seed)}
#[test]#[allow(clippy::expect_used)] // test should panic if verification failsfn signed_verify_roundtrip() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(*seed);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload);
let verified = signed .try_verify() .expect("verification should succeed for just-signed payload");
assert_eq!( verified.payload(), payload, "verified payload must match original" ); assert_eq!( verified.issuer(), &signing_key.verifying_key(), "issuer must match signer's public key" ); });}
#[test]fn signed_deterministic() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(*seed);
let signed1: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload); let signed2: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload);
// Ed25519 with dalek is deterministic (RFC 8032) assert_eq!(signed1, signed2, "same input must produce same signature"); });}
#[test]fn different_payloads_different_signatures() { check!() .with_type::<([u8; 32], Vec<u8>, Vec<u8>)>() .filter(|(_, a, b)| a != b) .for_each(|(seed, payload_a, payload_b)| { let signing_key = signing_key_from_seed(*seed);
let signed_a: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload_a); let signed_b: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload_b);
assert_ne!( signed_a.signature(), signed_b.signature(), "different payloads should produce different signatures" ); });}
#[test]fn wrong_key_fails_verification() { check!() .with_type::<([u8; 32], [u8; 32], Vec<u8>)>() .filter(|(a, b, _)| a != b) .for_each(|(seed_signer, seed_wrong, payload)| { let signing_key = signing_key_from_seed(*seed_signer); let wrong_key = signing_key_from_seed(*seed_wrong);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload);
let tampered: Signed<Vec<u8>, Ed25519, Identity> = Signed::from_unchecked_parts( wrong_key.verifying_key(), *signed.signature(), signed.encoded_payload().to_vec(), );
assert!( tampered.try_verify().is_err(), "verification must fail with wrong key" ); });}
#[test]#[allow(clippy::indexing_slicing)] // payload is non-empty (filter guarantees)fn tampered_payload_fails_verification() { check!() .with_type::<([u8; 32], Vec<u8>)>() .cloned() .filter(|(_, payload)| !payload.is_empty()) .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(seed);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, &payload);
let mut tampered_bytes = signed.encoded_payload().to_vec(); tampered_bytes[0] = tampered_bytes[0].wrapping_add(1);
let tampered: Signed<Vec<u8>, Ed25519, Identity> = Signed::from_unchecked_parts(*signed.issuer(), *signed.signature(), tampered_bytes);
assert!( tampered.try_verify().is_err(), "verification must fail with tampered payload" ); });}
#[test]#[allow(clippy::expect_used)] // test should panic if verification failsfn verified_into_parts() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(*seed);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload); let verified = signed.try_verify().expect("verification should succeed");
let expected_issuer = signing_key.verifying_key(); let (recovered_signed, recovered_payload) = verified.into_parts();
assert_eq!( recovered_signed.issuer(), &expected_issuer, "issuer must match" ); assert_eq!(&recovered_signed, &signed, "signed envelope must match"); assert_eq!(&recovered_payload, payload, "payload must match"); });}
#[test]fn verified_unchecked_roundtrip() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(*seed);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload);
let verified: Verified<Vec<u8>, Ed25519, Identity> = Verified::from_unchecked_parts(signed.clone(), payload.clone());
assert_eq!(verified.issuer(), &signing_key.verifying_key()); assert_eq!(verified.payload(), payload); assert_eq!(verified.signed(), &signed); });}
#[test]#[allow(clippy::expect_used)] // test should panic if verification failsfn verified_signed_back_ref() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(*seed);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload); let verified = signed.try_verify().expect("verification should succeed");
assert_eq!( verified.signed(), &signed, "verified must retain the original signed envelope" ); assert_eq!( verified.signed().encoded_payload(), signed.encoded_payload(), "encoded payload bytes must be preserved" ); assert_eq!( verified.signed().signature(), signed.signature(), "signature must be preserved" ); });}
#[test]#[allow(clippy::expect_used)] // test should panic if verification failsfn into_verified_roundtrip() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(*seed);
let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, payload); let signed_clone = signed.clone();
let verified = signed.into_verified().expect("verification should succeed");
assert_eq!( verified.payload(), payload, "verified payload must match original" ); assert_eq!( verified.signed(), &signed_clone, "signed envelope must be preserved" ); });}
#[test]fn seal_verified_roundtrip() { check!() .with_type::<([u8; 32], Vec<u8>)>() .cloned() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(seed);
let verified: Verified<Vec<u8>, Ed25519, Identity> = Signed::seal_verified(&signing_key, payload.clone());
assert_eq!( verified.payload(), &payload, "verified payload must match original" ); assert_eq!( verified.issuer(), &signing_key.verifying_key(), "issuer must match signer's public key" ); });}
#[test]#[allow(clippy::expect_used)] // test should panic if verification failsfn seal_verified_matches_seal_then_verify() { check!() .with_type::<([u8; 32], Vec<u8>)>() .cloned() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(seed);
// The two-step path let signed: Signed<Vec<u8>, Ed25519, Identity> = Signed::seal(&signing_key, &payload); let two_step = signed.try_verify().expect("verification should succeed");
// The one-step path let one_step: Verified<Vec<u8>, Ed25519, Identity> = Signed::seal_verified(&signing_key, payload.clone());
assert_eq!( two_step.payload(), one_step.payload(), "payloads must match" ); assert_eq!( two_step.signed(), one_step.signed(), "signed envelopes must be identical" ); });}
#[test]#[allow(clippy::expect_used)] // test should panic if verification failsfn seal_verified_envelope_verifies_independently() { check!() .with_type::<([u8; 32], Vec<u8>)>() .cloned() .for_each(|(seed, payload)| { let signing_key = signing_key_from_seed(seed);
let verified: Verified<Vec<u8>, Ed25519, Identity> = Signed::seal_verified(&signing_key, payload);
let re_verified = verified .signed() .try_verify() .expect("re-verification should succeed");
assert_eq!( re_verified.payload(), verified.payload(), "re-verified payload must match" ); });}