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
//! The `signature` module provides functionality for public, and private keys.

use generic_array::typenum::{U32, U64};
use generic_array::GenericArray;
use rand::{ChaChaRng, Rng, SeedableRng};
use rayon::prelude::*;
use ring::error::Unspecified;
use ring::rand::SecureRandom;
use ring::signature::Ed25519KeyPair;
use ring::{rand, signature};
use std::cell::RefCell;
use untrusted;

pub type KeyPair = Ed25519KeyPair;
pub type PublicKey = GenericArray<u8, U32>;
pub type Signature = GenericArray<u8, U64>;

pub trait KeyPairUtil {
    fn new() -> Self;
    fn pubkey(&self) -> PublicKey;
}

impl KeyPairUtil for Ed25519KeyPair {
    /// Return a new ED25519 keypair
    fn new() -> Self {
        let rng = rand::SystemRandom::new();
        let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng)
            .expect("generate_pkcs8 in signature pb fn new");
        signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes))
            .expect("from_pcks8 in signature pb fn new")
    }

    /// Return the public key for the given keypair
    fn pubkey(&self) -> PublicKey {
        GenericArray::clone_from_slice(self.public_key_bytes())
    }
}

pub trait SignatureUtil {
    fn verify(&self, peer_public_key_bytes: &[u8], msg_bytes: &[u8]) -> bool;
}

impl SignatureUtil for GenericArray<u8, U64> {
    fn verify(&self, peer_public_key_bytes: &[u8], msg_bytes: &[u8]) -> bool {
        let peer_public_key = untrusted::Input::from(peer_public_key_bytes);
        let msg = untrusted::Input::from(msg_bytes);
        let sig = untrusted::Input::from(self);
        signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok()
    }
}

pub struct GenKeys {
    // This is necessary because the rng needs to mutate its state to remain
    // deterministic, and the fill trait requires an immuatble reference to self
    generator: RefCell<ChaChaRng>,
}

impl GenKeys {
    pub fn new(seed: &[u8]) -> GenKeys {
        let seed32: Vec<_> = seed.iter().map(|&x| x as u32).collect();
        let rng = ChaChaRng::from_seed(&seed32);
        GenKeys {
            generator: RefCell::new(rng),
        }
    }

    pub fn new_key(&self) -> Vec<u8> {
        KeyPair::generate_pkcs8(self).unwrap().to_vec()
    }

    pub fn gen_n_seeds(&self, n: i64) -> Vec<[u8; 16]> {
        let mut rng = self.generator.borrow_mut();
        (0..n).map(|_| rng.gen()).collect()
    }

    pub fn gen_n_keypairs(&self, n: i64) -> Vec<KeyPair> {
        self.gen_n_seeds(n)
            .into_par_iter()
            .map(|seed| {
                let pkcs8 = GenKeys::new(&seed).new_key();
                KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8)).unwrap()
            })
            .collect()
    }
}

impl SecureRandom for GenKeys {
    fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
        let mut rng = self.generator.borrow_mut();
        rng.fill_bytes(dest);
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashSet;

    #[test]
    fn test_new_key_is_deterministic() {
        let seed = [1, 2, 3, 4];
        let rng0 = GenKeys::new(&seed);
        let rng1 = GenKeys::new(&seed);

        for _ in 0..100 {
            assert_eq!(rng0.new_key(), rng1.new_key());
        }
    }

    fn gen_n_pubkeys(seed: &[u8], n: i64) -> HashSet<PublicKey> {
        GenKeys::new(&seed)
            .gen_n_keypairs(n)
            .into_iter()
            .map(|x| x.pubkey())
            .collect()
    }

    #[test]
    fn test_gen_n_pubkeys_deterministic() {
        let seed = [1, 2, 3, 4];
        assert_eq!(gen_n_pubkeys(&seed, 50), gen_n_pubkeys(&seed, 50));
    }
}

#[cfg(all(feature = "unstable", test))]
mod bench {
    extern crate test;

    use self::test::Bencher;
    use super::*;

    #[bench]
    fn bench_gen_keys(b: &mut Bencher) {
        let seed: &[_] = &[1, 2, 3, 4];
        let rnd = GenKeys::new(seed);
        b.iter(|| rnd.gen_n_keypairs(1000));
    }
}