routing 0.37.1

A secured storage DHT
// Copyright 2018 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

//! Mock cryptographic primitives.
//!
//! These primitives are designed to be very fast (several times faster than the real ones), but
//! they are NOT secure. They are supposed to be used for testing only.

/// Mock version of a subset of the `rust_sodium` crate.
pub mod rust_sodium {
    use rand::{Rng, SeedableRng, XorShiftRng};
    use std::cell::RefCell;

    thread_local! {
        static RNG: RefCell<XorShiftRng> = RefCell::new(XorShiftRng::new_unseeded());
    }

    /// Initialise mock `rust_sodium`.
    pub fn init() -> bool {
        true
    }

    /// Initialise mock `rust_sodium` with the given random number generator. This can be used to
    /// guarantee reproducible test results.
    pub fn init_with_rng<T: Rng>(other: &mut T) -> Result<(), i32> {
        RNG.with(|rng| rng.borrow_mut().reseed(other.gen()));
        Ok(())
    }

    /// Mock cryptographic functions.
    pub mod crypto {
        /// Mock signing.
        pub mod sign {
            use super::super::with_rng;
            use rand::Rng;
            use std::ops::{Index, RangeFull};

            /// Number of bytes in a `PublicKey`.
            pub const PUBLICKEYBYTES: usize = 32;
            /// Number of bytes in a `SecretKey`.
            pub const SECRETKEYBYTES: usize = 32;
            /// Number of bytes in a `Signature`.
            pub const SIGNATUREBYTES: usize = 32;

            /// Mock signing public key.
            #[derive(
                Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
            )]
            pub struct PublicKey(pub [u8; PUBLICKEYBYTES]);

            impl Index<RangeFull> for PublicKey {
                type Output = [u8];
                fn index(&self, index: RangeFull) -> &[u8] {
                    self.0.index(index)
                }
            }

            /// Mock signing secret key.
            #[derive(Clone, Debug, Eq, PartialEq)]
            pub struct SecretKey(pub [u8; SECRETKEYBYTES]);

            /// Mock signature.
            #[derive(
                Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, Serialize, PartialEq, PartialOrd,
            )]
            pub struct Signature(pub [u8; SIGNATUREBYTES]);

            impl AsRef<[u8]> for Signature {
                fn as_ref(&self) -> &[u8] {
                    &self.0
                }
            }

            /// Generate mock public and corresponding secret key.
            pub fn gen_keypair() -> (PublicKey, SecretKey) {
                with_rng(|rng| {
                    let value = rng.gen();
                    (PublicKey(value), SecretKey(value))
                })
            }

            /// Sign a message using the mock secret key.
            pub fn sign_detached(m: &[u8], sk: &SecretKey) -> Signature {
                let mut temp = m.to_vec();
                temp.extend(&sk.0);
                Signature(hash256(&temp))
            }

            /// Verify the mock signature against the message and the signer's mock public key.
            pub fn verify_detached(signature: &Signature, m: &[u8], pk: &PublicKey) -> bool {
                let mut temp = m.to_vec();
                temp.extend(&pk.0);
                *signature == Signature(hash256(&temp))
            }

            fn hash256(data: &[u8]) -> [u8; 32] {
                use tiny_keccak::sha3_256;
                sha3_256(data)
            }
        }

        /// Mock encryption.
        pub mod box_ {
            use super::super::with_rng;
            use rand::Rng;

            /// Number of bytes in a `PublicKey`.
            pub const PUBLICKEYBYTES: usize = 32;
            /// Number of bytes in a `SecretKey`.
            pub const SECRETKEYBYTES: usize = 32;
            /// Number of bytes in a `Nonce`.
            pub const NONCEBYTES: usize = 4;

            /// Mock public key for asymmetric encryption/decryption.
            #[derive(
                Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
            )]
            pub struct PublicKey(pub [u8; PUBLICKEYBYTES]);

            /// Mock secret key for asymmetric encryption/decryption.
            #[derive(Clone, Debug, Eq, PartialEq)]
            pub struct SecretKey(pub [u8; SECRETKEYBYTES]);

            /// Mock nonce for asymmetric encryption/decryption.
            pub struct Nonce(pub [u8; NONCEBYTES]);

            /// Generate mock public and corresponding secret key.
            pub fn gen_keypair() -> (PublicKey, SecretKey) {
                with_rng(|rng| {
                    let value = rng.gen();
                    (PublicKey(value), SecretKey(value))
                })
            }

            /// Generate mock nonce.
            pub fn gen_nonce() -> Nonce {
                with_rng(|rng| Nonce(rng.gen()))
            }

            /// Perform mock encryption of the given message using their public key, our secret key
            /// and nonce.
            pub fn seal(m: &[u8], nonce: &Nonce, pk: &PublicKey, sk: &SecretKey) -> Vec<u8> {
                let mut result =
                    Vec::with_capacity(m.len() + nonce.0.len() + pk.0.len() + sk.0.len());
                result.extend(&nonce.0);
                result.extend(&pk.0);
                result.extend(&sk.0);
                result.extend(m);
                result
            }

            /// Perform mock decryption of the given ciphertext using their secret key, our public
            /// key and nonce.
            pub fn open(
                c: &[u8],
                nonce: &Nonce,
                pk: &PublicKey,
                sk: &SecretKey,
            ) -> Result<Vec<u8>, ()> {
                let n = nonce.0.len();
                let p = pk.0.len();
                let s = sk.0.len();

                if c[0..n] != nonce.0 {
                    return Err(());
                }

                if c[n..n + p] != sk.0 {
                    return Err(());
                }

                if c[n + p..n + p + s] != pk.0 {
                    return Err(());
                }

                Ok(c[n + p + s..].to_vec())
            }
        }
    }

    fn with_rng<F, R>(f: F) -> R
    where
        F: FnOnce(&mut XorShiftRng) -> R,
    {
        RNG.with(|rng| f(&mut *rng.borrow_mut()))
    }
}

#[cfg(test)]
mod tests {
    use super::rust_sodium::crypto::{box_, sign};
    use rand::{self, Rng};

    #[test]
    fn keypair_generation() {
        let (sign_pk0, sign_sk0) = sign::gen_keypair();
        let (sign_pk1, sign_sk1) = sign::gen_keypair();
        assert_ne!(sign_pk0, sign_pk1);
        assert_ne!(sign_sk0, sign_sk1);

        let (box_pk0, box_sk0) = box_::gen_keypair();
        let (box_pk1, box_sk1) = box_::gen_keypair();
        assert_ne!(box_pk0, box_pk1);
        assert_ne!(box_sk0, box_sk1);
    }

    #[test]
    fn sign_and_verify() {
        let (pk0, sk0) = sign::gen_keypair();
        let message: Vec<_> = rand::thread_rng().gen_iter().take(10).collect();

        let signature = sign::sign_detached(&message, &sk0);
        assert!(sign::verify_detached(&signature, &message, &pk0));

        let (pk1, _) = sign::gen_keypair();
        assert!(!sign::verify_detached(&signature, &message, &pk1));
    }

    #[test]
    fn seal_and_open() {
        let (pk0, sk0) = box_::gen_keypair();
        let (pk1, sk1) = box_::gen_keypair();
        let nonce0 = box_::gen_nonce();

        let original: Vec<_> = rand::thread_rng().gen_iter().take(10).collect();
        let encrypted = box_::seal(&original, &nonce0, &pk0, &sk1);
        let decrypted = unwrap!(box_::open(&encrypted, &nonce0, &pk1, &sk0));
        assert_eq!(decrypted, original);

        assert!(box_::open(&encrypted, &nonce0, &pk0, &sk0).is_err());
        assert!(box_::open(&encrypted, &nonce0, &pk0, &sk1).is_err());
        assert!(box_::open(&encrypted, &nonce0, &pk1, &sk1).is_err());
    }
}