Something went wrong. Try again.
Typelevel cryptographic algo tracking crates.io/crates/evidence
typelevel cryptography util
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124//! Property-based tests for Encrypted.
#![cfg(feature = "chacha20poly1305")]
use bolero::check;use evidence::{ codec::Identity, encrypted::{Encrypted, EncryptedUnchecked}, encryption::chacha20poly1305::ChaCha20Poly1305,};
/// Helper to create a key from seed bytes.fn key_from_seed(seed: [u8; 32]) -> chacha20poly1305::Key { chacha20poly1305::Key::from(seed)}
#[test]#[allow(clippy::expect_used)] // test should panic if decryption failsfn encrypted_decrypt_roundtrip() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, plaintext)| { let key = key_from_seed(*seed);
let encrypted: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt(&key, plaintext);
let decrypted = encrypted .try_decrypt(&key) .expect("decryption should succeed for just-encrypted payload");
assert_eq!( &decrypted, plaintext, "decrypted payload must match original" ); });}
#[test]fn encrypted_different_nonces() { check!() .with_type::<([u8; 32], Vec<u8>)>() .for_each(|(seed, plaintext)| { let key = key_from_seed(*seed);
let encrypted1: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt(&key, plaintext); let encrypted2: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt(&key, plaintext);
assert_ne!( encrypted1.nonce(), encrypted2.nonce(), "different encryptions should use different nonces" ); });}
#[test]fn wrong_key_fails_decryption() { check!() .with_type::<([u8; 32], [u8; 32], Vec<u8>)>() .filter(|(a, b, _)| a != b) .for_each(|(seed_correct, seed_wrong, plaintext)| { let correct_key = key_from_seed(*seed_correct); let wrong_key = key_from_seed(*seed_wrong);
let encrypted: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt(&correct_key, plaintext);
assert!( encrypted.try_decrypt(&wrong_key).is_err(), "decryption must fail with wrong key" ); });}
#[test]#[allow(clippy::indexing_slicing)] // ciphertext is non-empty (filter guarantees)fn tampered_ciphertext_fails_decryption() { check!() .with_type::<([u8; 32], Vec<u8>)>() .cloned() .filter(|(_, plaintext)| !plaintext.is_empty()) .for_each(|(seed, plaintext)| { let key = key_from_seed(seed);
let encrypted: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt(&key, &plaintext);
let mut tampered_ciphertext = encrypted.ciphertext().to_vec(); tampered_ciphertext[0] = tampered_ciphertext[0].wrapping_add(1);
let tampered: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::from_unchecked_parts(tampered_ciphertext, *encrypted.nonce());
assert!( tampered.try_decrypt(&key).is_err(), "decryption must fail with tampered ciphertext" ); });}
#[test]fn deterministic_with_same_nonce() { check!() .with_type::<([u8; 32], [u8; 12], Vec<u8>)>() .for_each(|(seed, nonce_bytes, plaintext)| { let key = key_from_seed(*seed); let nonce = hybrid_array::Array::from(*nonce_bytes);
let encrypted1: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt_with_nonce(&key, &nonce, plaintext); let encrypted2: Encrypted<Vec<u8>, ChaCha20Poly1305, Identity> = Encrypted::encrypt_with_nonce(&key, &nonce, plaintext);
assert_eq!( encrypted1.ciphertext(), encrypted2.ciphertext(), "same key + nonce + plaintext must produce same ciphertext" ); });}