use super::*;
use crate::digest;
use proptest::prelude::*;
use quickcheck::{Arbitrary, Gen};
use rand::rngs::SmallRng;
use rand_core::{CryptoRng, Error as RngError, RngCore, SeedableRng};
#[derive(Clone, Debug, test_strategy::Arbitrary)]
pub struct TestCryptoGen(pub u64);
pub struct TestCryptoRng(SmallRng);
impl RngCore for TestCryptoRng {
fn next_u32(&mut self) -> u32 {
self.0.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.0.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.0.fill_bytes(dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), RngError> {
self.0.try_fill_bytes(dest)
}
}
impl SeedableRng for TestCryptoRng {
type Seed = <SmallRng as SeedableRng>::Seed;
fn from_seed(seed: Self::Seed) -> Self {
Self(SmallRng::from_seed(seed))
}
}
impl CryptoRng for TestCryptoRng {}
impl Arbitrary for TestCryptoGen {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
TestCryptoGen(Arbitrary::arbitrary(g))
}
}
impl TestCryptoGen {
pub fn get_rng(&self, idx: u32) -> TestCryptoRng {
TestCryptoRng::seed_from_u64((idx as u64) * 4096 + self.0)
}
pub fn secret_key<A: AsymmetricKey>(&self, idx: u32) -> SecretKey<A> {
SecretKey::generate(self.get_rng(idx))
}
pub fn keypair<A: AsymmetricKey>(&self, idx: u32) -> KeyPair<A> {
KeyPair::from(self.secret_key(idx))
}
}
#[allow(dead_code)]
pub fn arbitrary_public_key<A: AsymmetricKey, G: Gen>(g: &mut G) -> PublicKey<A::PubAlg> {
TestCryptoGen::arbitrary(g)
.keypair::<A>(0)
.public_key()
.clone()
}
pub fn arbitrary_secret_key<A, G>(g: &mut G) -> SecretKey<A>
where
A: AsymmetricKey,
G: Gen,
{
TestCryptoGen::arbitrary(g).secret_key(0)
}
#[allow(dead_code)]
pub fn static_secret_key<A>() -> SecretKey<A>
where
A: AsymmetricKey,
{
let rng = TestCryptoRng::seed_from_u64(0xfedc_ba98);
SecretKey::generate(rng)
}
impl<A> Arbitrary for SecretKey<A>
where
A: AsymmetricKey + 'static,
A::Secret: Send,
{
fn arbitrary<G: Gen>(g: &mut G) -> Self {
arbitrary_secret_key(g)
}
}
impl<A> Arbitrary for KeyPair<A>
where
A: AsymmetricKey + 'static,
A::Secret: Send,
<A::PubAlg as AsymmetricPublicKey>::Public: Send,
{
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let secret_key = SecretKey::arbitrary(g);
KeyPair::from(secret_key)
}
}
impl<T, A> Arbitrary for Signature<T, A>
where
A: VerificationAlgorithm + 'static,
A::Signature: Send,
T: Send + 'static,
{
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let bytes: Vec<_> = std::iter::repeat_with(|| u8::arbitrary(g))
.take(A::SIGNATURE_SIZE)
.collect();
Signature::from_binary(&bytes).unwrap()
}
}
impl Arbitrary for Blake2b256 {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let bytes: Vec<_> = std::iter::repeat_with(|| u8::arbitrary(g))
.take(Self::HASH_SIZE)
.collect();
Self::try_from_slice(&bytes).unwrap()
}
}
impl<H: digest::DigestAlg + 'static> Arbitrary for digest::Digest<H> {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let bytes: Vec<_> = std::iter::repeat_with(|| u8::arbitrary(g))
.take(26) .collect();
digest::Digest::<H>::digest(&bytes[..])
}
}
impl<H: digest::DigestAlg + 'static, T: 'static + Send> Arbitrary for digest::DigestOf<H, T> {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let bytes: Vec<_> = std::iter::repeat_with(|| u8::arbitrary(g))
.take(26) .collect();
digest::DigestOf::<H, Vec<u8>>::digest(&bytes).coerce()
}
}
pub fn public_key_strategy<A: AsymmetricKey>() -> impl Strategy<Value = PublicKey<A::PubAlg>> {
any::<(TestCryptoGen, u32)>()
.prop_map(|(gen, idx)| SecretKey::<A>::generate(gen.get_rng(idx)).to_public())
}