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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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};

/// an Arbitrary friendly cryptographic generator
///
/// Given the same generation, all the cryptographic
/// material that is created through it, is
/// deterministic, and thus can be replay
///
/// For obvious reasons, do *not* use anywhere except for testing
#[derive(Clone, Debug, test_strategy::Arbitrary)]
pub struct TestCryptoGen(pub u64);

/// A faster non-cryptographic RNG to be used in tests. NOTE: this RNG does
/// implement `CryptoRng`, but it is not really cryptographic. It MUST NOT be
/// used in the production code.
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 {
    /// get the nth deterministic RNG
    pub fn get_rng(&self, idx: u32) -> TestCryptoRng {
        TestCryptoRng::seed_from_u64((idx as u64) * 4096 + self.0)
    }

    /// Get the nth deterministic secret key
    pub fn secret_key<A: AsymmetricKey>(&self, idx: u32) -> SecretKey<A> {
        SecretKey::generate(self.get_rng(idx))
    }

    /// Get the nth deterministic keypair
    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) // actual number doesn't really matter
            .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) // actual number doesn't really matter
            .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())
}