use std::collections::BTreeMap;
use proptest::prelude::*;
use enprot::crypto::{CryptoPolicy, CryptoPolicyDefault};
use enprot::etree::{CipherOptions, PBKDFOptions};
use enprot::prot::{decrypt, encrypt};
fn policy() -> Box<dyn CryptoPolicy> {
Box::new(CryptoPolicyDefault {})
}
fn new_rng() -> Option<botan::RandomNumberGenerator> {
Some(botan::RandomNumberGenerator::new().unwrap())
}
fn pbkdf_opts() -> PBKDFOptions {
let mut params = BTreeMap::new();
params.insert("i".to_string(), 1000);
PBKDFOptions {
alg: "pbkdf2-sha256".to_string(),
saltlen: 0,
salt: Some(b"01234567".to_vec()),
msec: None,
params: Some(params),
}
}
fn cipher_opts(alg: &str) -> CipherOptions {
CipherOptions {
alg: alg.to_string(),
iv: None,
compress: false,
}
}
fn round_trip_with(pt: &[u8], password: &str, alg: &str) -> Vec<u8> {
let policy = policy();
let mut cache: Option<Vec<_>> = Some(Vec::new());
let (ct, extfields) = encrypt(
pt.to_vec(),
password,
&mut new_rng(),
&pbkdf_opts(),
&cipher_opts(alg),
&mut cache,
&*policy,
)
.expect("encrypt");
decrypt(
ct,
password,
&extfields.get("pbkdf"),
&extfields.get("cipher"),
&extfields.get("compress"),
&mut cache,
&*policy,
)
.expect("decrypt")
}
fn encrypt_with(pt: &[u8], password: &str, alg: &str) -> Vec<u8> {
let policy = policy();
let mut cache: Option<Vec<_>> = Some(Vec::new());
let (ct, _) = encrypt(
pt.to_vec(),
password,
&mut new_rng(),
&pbkdf_opts(),
&cipher_opts(alg),
&mut cache,
&*policy,
)
.expect("encrypt");
ct
}
proptest! {
#[test]
fn round_trip_aes_256_gcm_siv_det(
pt in prop::collection::vec(any::<u8>(), 0..4096),
password in "[a-zA-Z0-9]{1,64}",
) {
let recovered = round_trip_with(&pt, &password, "aes-256-gcm-siv-det");
prop_assert_eq!(recovered, pt);
}
#[test]
fn round_trip_aes_256_gcm_det(
pt in prop::collection::vec(any::<u8>(), 0..4096),
password in "[a-zA-Z0-9]{1,64}",
) {
let recovered = round_trip_with(&pt, &password, "aes-256-gcm-det");
prop_assert_eq!(recovered, pt);
}
#[test]
fn determinism_aes_256_gcm_siv_det(
pt in prop::collection::vec(any::<u8>(), 0..1024),
password in "[a-zA-Z0-9]{1,32}",
) {
let ct_a = encrypt_with(&pt, &password, "aes-256-gcm-siv-det");
let ct_b = encrypt_with(&pt, &password, "aes-256-gcm-siv-det");
prop_assert_eq!(ct_a, ct_b, "deterministic mode must produce identical ciphertexts");
}
}