,
43 | },
44 | }
45 |
46 | pub type KeyPair = (Rsa, Rsa);
47 |
48 | impl Rsa {
49 | pub fn keypair_from_primes(p: P, q: Q, e: E) -> KeyPair
50 | where P: Into,
51 | Q: Into,
52 | E: Into
53 | {
54 | let (p, q, e) = (p.into(), q.into(), e.into());
55 |
56 | let n = &p * &q;
57 | let phi_n = &n - (&p + &q - BigUint::one());
58 |
59 | let d = e.inverse(&phi_n).expect("e is irreversible in ring phi(pq) - error");
60 |
61 | let public = Rsa::Public {
62 | n: n.clone(),
63 | e: e,
64 | };
65 | let private = Rsa::Private {
66 | n: n,
67 | extra: Some(SecretKeyExtra::from_primes(p, q, &d)),
68 | d: d,
69 | };
70 |
71 | (public, private)
72 | }
73 |
74 | pub fn generate_keypair(mut rng: G, e: T, bits: usize) -> KeyPair
75 | where G: Rng + RandBigInt,
76 | T: Into
77 | {
78 | let e = e.into();
79 |
80 | let mut p = generate_prime(&mut rng, bits).expect("Cannot generate safe prime");
81 | while (&p - BigUint::one()) % &e != BigUint::one() {
82 | p = generate_prime(&mut rng, bits).expect("Cannot generate safe prime");
83 | }
84 | let mut q = generate_prime(&mut rng, bits).expect("Cannot generate safe prime");
85 | while (&q - BigUint::one()) % &e != BigUint::one() {
86 | q = generate_prime(&mut rng, bits).expect("Cannot generate safe prime");
87 | }
88 |
89 | Self::keypair_from_primes(p, q, e)
90 | }
91 |
92 | pub fn is_public(&self) -> bool {
93 | match *self {
94 | Rsa::Public { .. } => true,
95 | _ => false,
96 | }
97 | }
98 |
99 | pub fn is_private(&self) -> bool {
100 | match *self {
101 | Rsa::Private { .. } => true,
102 | _ => false,
103 | }
104 | }
105 |
106 | pub fn crypt(&self, msg: &BigUint) -> BigUint {
107 | match *self {
108 | Rsa::Private { ref n, ref d, ref extra } => crypt(msg, n, d, extra.as_ref()),
109 | Rsa::Public { ref n, ref e } => crypt(msg, n, e, None),
110 | }
111 | }
112 | }
113 |
114 | fn crypt(msg: &BigUint,
115 | modulus: &BigUint,
116 | exp: &BigUint,
117 | extra: Option<&SecretKeyExtra>)
118 | -> BigUint {
119 | if let Some(ref extra) = extra {
120 | chinese_remainders_power(msg, extra)
121 | } else {
122 | msg.pow_mod(exp, modulus)
123 | }
124 | }
125 |
126 | fn chinese_remainders_power(c: &BigUint, extra: &SecretKeyExtra) -> BigUint {
127 | let mut m1 = c.pow_mod(&extra.dmp1, &extra.p);
128 | let m2 = c.pow_mod(&extra.dmq1, &extra.q);
129 |
130 | while m1 < m2 {
131 | m1 = m1 + &extra.p;
132 | }
133 |
134 | let h = (&extra.qinv * (m1 - &m2)) % &extra.p;
135 |
136 | m2 + h * &extra.q
137 | }
138 |
--------------------------------------------------------------------------------
/crypto/src/asymmetric/utils/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod modular;
2 | pub mod primes;
3 |
--------------------------------------------------------------------------------
/crypto/src/asymmetric/utils/modular/inverse.rs:
--------------------------------------------------------------------------------
1 | use num::{Zero, One, Signed};
2 | use bigint::{BigUint, BigInt, Sign};
3 |
4 | pub trait Inverse {
5 | type Output;
6 |
7 | fn inverse(self, modulo: Self) -> Option;
8 | }
9 |
10 | impl<'a> Inverse for &'a BigUint {
11 | type Output = BigUint;
12 |
13 | fn inverse(self, modulo: Self) -> Option {
14 | BigInt::from_biguint(Sign::Plus, self.clone())
15 | .inverse(&BigInt::from_biguint(Sign::Plus, modulo.clone()))
16 | .and_then(|n| n.to_biguint())
17 | }
18 | }
19 |
20 | impl<'a> Inverse for &'a BigInt {
21 | type Output = BigInt;
22 |
23 | fn inverse(self, modulo: Self) -> Option {
24 | let (mut t, mut new_t): (BigInt, BigInt) = (Zero::zero(), One::one());
25 | let (mut r, mut new_r): (BigInt, BigInt) = (modulo.clone(), self.clone());
26 |
27 | while !new_r.is_zero() {
28 | let quo = &r / &new_r;
29 | let tmp = &r - &quo * &new_r;
30 | r = new_r;
31 | new_r = tmp;
32 | let tmp = &t - &quo * &new_t;
33 | t = new_t;
34 | new_t = tmp;
35 | }
36 |
37 | if r != One::one() {
38 | return None;
39 | }
40 | if t.is_negative() {
41 | Some(t + modulo)
42 | } else {
43 | Some(t)
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/crypto/src/asymmetric/utils/modular/mod.rs:
--------------------------------------------------------------------------------
1 | pub use self::inverse::Inverse;
2 | pub use self::power::Power;
3 |
4 | pub mod inverse;
5 | pub mod power;
6 |
--------------------------------------------------------------------------------
/crypto/src/asymmetric/utils/modular/power.rs:
--------------------------------------------------------------------------------
1 | use num::{One, Zero};
2 | use bigint::BigUint;
3 | use integer::Integer;
4 |
5 | pub trait Power {
6 | type Output;
7 |
8 | fn pow_mod(self, exp: T, modulus: T) -> Self::Output;
9 | }
10 |
11 | impl Power for BigUint {
12 | type Output = Self;
13 |
14 | fn pow_mod(self, exp: BigUint, modulus: BigUint) -> Self {
15 | (&self).pow_mod(&exp, &modulus)
16 | }
17 | }
18 |
19 | impl<'a> Power<&'a BigUint> for &'a BigUint {
20 | type Output = BigUint;
21 |
22 | fn pow_mod(self, exp: &BigUint, modulus: &BigUint) -> BigUint {
23 | let mut base = self % modulus;
24 | let mut exp = exp.clone();
25 |
26 | if exp == One::one() {
27 | return base;
28 | }
29 |
30 | let mut acc: BigUint = One::one();
31 |
32 | while exp > Zero::zero() {
33 | if exp.is_odd() {
34 | acc = (acc * &base) % modulus
35 | }
36 | if exp > One::one() {
37 | base = (&base * &base) % modulus
38 | }
39 | exp = exp >> 1;
40 | }
41 |
42 | acc
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/crypto/src/asymmetric/utils/primes/mod.rs:
--------------------------------------------------------------------------------
1 | use num::One;
2 | use integer::Integer;
3 | use bigint::{BigUint, RandBigInt};
4 | use rand::Rng;
5 |
6 | use asymmetric::utils::primes::tests::PrimeTest;
7 |
8 | pub mod tests;
9 |
10 | const PRIME_TEST_COUNT: usize = 20;
11 |
12 | /// Generate new prime number with given bit size via given random number generator.
13 | ///
14 | /// Currently this function give guarantee that it ever ends. In case of bad `Rng` engine
15 | /// this could fall into endless loop.
16 | ///
17 | /// This function doesn't reseed `Rng` so You must provide autoreseedable engine, check out
18 | /// [`ReseedingRng`](http://doc.rust-lang.org/rand/rand/reseeding/struct.ReseedingRng.html).
19 | pub fn generate_prime(gen: &mut T, bits: usize) -> Option {
20 | loop {
21 | let mut int = gen.gen_biguint(bits);
22 |
23 | if int.is_even() {
24 | int = int + BigUint::one();
25 | }
26 |
27 | if tests::Fermat(gen).test_loop(&int, PRIME_TEST_COUNT).is_composite() {
28 | continue;
29 | }
30 | if tests::MillerRabin(gen).test_loop(&int, PRIME_TEST_COUNT).is_composite() {
31 | continue;
32 | }
33 |
34 | return Some(int);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/crypto/src/asymmetric/utils/primes/tests.rs:
--------------------------------------------------------------------------------
1 | use num::One;
2 | use integer::Integer;
3 | use bigint::{ToBigUint, BigUint};
4 | use rand::Rng;
5 |
6 | use asymmetric::utils::modular::power::Power;
7 |
8 | #[derive(Debug, PartialEq, Eq, Copy, Clone)]
9 | pub enum Type {
10 | PropablyPrime,
11 | Composite,
12 | }
13 |
14 | impl Type {
15 | pub fn is_composite(&self) -> bool {
16 | match *self {
17 | Type::Composite => true,
18 | _ => false,
19 | }
20 | }
21 | }
22 |
23 | pub trait PrimeTest {
24 | fn test(&mut self, num: &BigUint) -> Type;
25 |
26 | fn test_loop(&mut self, num: &BigUint, times: usize) -> Type {
27 | for _ in 0..times {
28 | if self.test(num).is_composite() {
29 | return Type::Composite;
30 | }
31 | }
32 |
33 | Type::PropablyPrime
34 | }
35 | }
36 |
37 | pub struct Fermat<'a, T: Rng + 'a>(pub &'a mut T);
38 |
39 | impl<'a, T: Rng + 'a> PrimeTest for Fermat<'a, T> {
40 | fn test(&mut self, num: &BigUint) -> Type {
41 | let base = self.0.next_u64().to_biguint().unwrap();
42 | let num_1 = num - BigUint::one();
43 |
44 | if (&base).pow_mod(&num_1, num) != BigUint::one() {
45 | Type::Composite
46 | } else {
47 | Type::PropablyPrime
48 | }
49 | }
50 | }
51 |
52 | pub struct MillerRabin<'a, T: Rng + 'a>(pub &'a mut T);
53 |
54 | impl<'a, T: Rng + 'a> MillerRabin<'a, T> {
55 | fn greatest_2_divisor(num: &BigUint) -> (usize, BigUint) {
56 | let mut s = 0;
57 | let mut num = num - BigUint::one();
58 | while num.is_even() {
59 | num = num >> 1;
60 | s += 1;
61 | }
62 |
63 | (s, num)
64 | }
65 |
66 | fn witness(num: &BigUint, a: BigUint, d: &BigUint, s: usize) -> Type {
67 | let mut x = (&a).pow_mod(d, num);
68 | let num_1 = num - BigUint::one();
69 |
70 | if x == BigUint::one() || x == num_1 {
71 | return Type::PropablyPrime;
72 | }
73 |
74 | for _ in 0..s {
75 | x = (&x * &x) % num;
76 | if x == BigUint::one() {
77 | return Type::Composite;
78 | }
79 | if x == num_1 {
80 | return Type::PropablyPrime;
81 | }
82 | }
83 |
84 | Type::Composite
85 | }
86 | }
87 |
88 | impl<'a, T: Rng + 'a> PrimeTest for MillerRabin<'a, T> {
89 | fn test(&mut self, num: &BigUint) -> Type {
90 | let a = self.0.next_u64().to_biguint().unwrap();
91 | let (s, d) = Self::greatest_2_divisor(num);
92 |
93 | Self::witness(num, a, &d, s)
94 | }
95 | }
96 |
97 | #[cfg(test)]
98 | mod tests {
99 | use rand::{StdRng, SeedableRng};
100 |
101 | const SEED: [usize; 1] = [0x00];
102 |
103 | fn rng() -> StdRng {
104 | StdRng::from_seed(&SEED[..])
105 | }
106 |
107 | mod fermat {
108 | use bigint::ToBigUint;
109 |
110 | use super::rng;
111 | use super::super::{PrimeTest, Type, Fermat};
112 |
113 | #[test]
114 | fn prime() {
115 | let mut rng = rng();
116 | let mut fermat = Fermat(&mut rng);
117 | let res = fermat.test_loop(&4393139u64.to_biguint().unwrap(), 20);
118 |
119 | assert_eq!(res, Type::PropablyPrime);
120 | }
121 |
122 | #[test]
123 | fn composite() {
124 | let mut rng = rng();
125 | let mut fermat = Fermat(&mut rng);
126 | let res = fermat.test_loop(&4393137u64.to_biguint().unwrap(), 20);
127 |
128 | assert_eq!(res, Type::Composite);
129 | }
130 | }
131 |
132 | mod miller_rabin {
133 | use bigint::ToBigUint;
134 |
135 | use super::rng;
136 | use super::super::{PrimeTest, Type, MillerRabin};
137 |
138 | #[test]
139 | fn prime() {
140 | let mut rng = rng();
141 | let mut miller_rabin = MillerRabin(&mut rng);
142 | let res = miller_rabin.test_loop(&4393139u64.to_biguint().unwrap(), 20);
143 |
144 | assert_eq!(res, Type::PropablyPrime);
145 | }
146 |
147 | #[test]
148 | fn composite() {
149 | let mut rng = rng();
150 | let mut miller_rabin = MillerRabin(&mut rng);
151 | let res = miller_rabin.test_loop(&4393137u64.to_biguint().unwrap(), 20);
152 |
153 | assert_eq!(res, Type::Composite);
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/crypto/src/block/mod.rs:
--------------------------------------------------------------------------------
1 | //! Block cryptosystems
2 |
3 | use generic_array::ArrayLength;
4 | use typenum::uint::Unsigned;
5 |
6 | pub mod blowfish;
7 |
8 | /// Block encryptor definition
9 | pub trait BlockEncrypt {
10 | /// Single block size
11 | type BlockSize: Unsigned + ArrayLength;
12 |
13 | /// Single block size
14 | fn block_size() -> usize {
15 | Self::BlockSize::to_usize()
16 | }
17 |
18 | /// Encrypt single block of data
19 | fn encrypt_block(&self, input: I, output: O)
20 | where I: AsRef<[u8]>,
21 | O: AsMut<[u8]>;
22 | }
23 |
24 | /// Block decryptor definition
25 | pub trait BlockDecrypt {
26 | /// Single block size
27 | type BlockSize: Unsigned + ArrayLength;
28 |
29 | /// Single block size
30 | fn block_size() -> usize {
31 | Self::BlockSize::to_usize()
32 | }
33 |
34 | /// Decrypt single block of data
35 | fn decrypt_block(&self, input: I, output: O)
36 | where I: AsRef<[u8]>,
37 | O: AsMut<[u8]>;
38 | }
39 |
--------------------------------------------------------------------------------
/crypto/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! Cryptosystems primitives
2 | //!
3 | //! Cryptosystem is a suite of algorithms that describe particular security service, in most cases
4 | //! used for achieving confidentiality. Typically this is set of three algorithms: key generation,
5 | //! encryption function and decryption function.
6 | //!
7 | //! Mathematically it can be described as tuple \\((\mathcal{P, C, K, E, D})\\), where:
8 | //!
9 | //! - \\(\mathcal{P}\\) is a set called "plaintext space"
10 | //! - \\(\mathcal{C}\\) is a set called "ciphertext space"
11 | //! - \\(\mathcal{K}\\) is a set called "key space"
12 | //! - \\(\mathcal{E} = \left\\{E_k : k \in \mathcal{K}\right\\}\\) is a set of functions
13 | //! \\(E_k : \mathcal{P} \to \mathcal{C}\\) called "encryption functions"
14 | //! - \\(\mathcal{D} = \left\\{E_k : k \in \mathcal{K}\right\\}\\) is a set of functions
15 | //! \\(D_k : \mathcal{C} \to \mathcal{P}\\) called "decryption functions"
16 | //!
17 | //! For each \\(e \in K\\) there is \\(d \in K\\) such that \\(D_d(E_e(p))) = p\\).
18 | //! If \\(d = e\\) then we call that "symmetric cipher" otherwise we call it "asymmetric cipher".
19 | //!
20 | //! In practise we use "asymmetric ciphers" for which computing \\(d\\) from \\(e\\) is computationally
21 | //! hard or impossible.
22 | //!
23 | //! # Kerckhoff's Principle
24 | //!
25 | //! > A cryptosystem should be secure even if everything about the system, except the key, is
26 | //! > public knowledge.
27 | //!
28 | //! This is basic law for moder cryptography. Unfortunately many of people understand this as
29 | //! "keeping cryptosystem hidden is bad". That is big misunderstanding of what that principle
30 | //! states. It is nothing bad to keep cryptosystem in secret, it is yet another obstacle to
31 | //! overcome by eavesdropper, just don't rely on secrecy.
32 | //!
33 | //! # Key lengths
34 | //!
35 | //! According to [ECRYPT II][ecrypt] [Yearly Report on Algorithms and Keysizes][d.spa.20] this
36 | //! table presents key-sizes equivalence between types of algorithms:
37 | //!
38 | //! | Symmetric | Factoring Modulus | Discrete Logarithm | Elliptic Curves |
39 | //! | --------: | ----------------: | -----------------: | --------------: |
40 | //! | 48 | 480 | 480/96 | 96 |
41 | //! | 56 | 640 | 640/112 | 112 |
42 | //! | 64 | 816 | 816/128 | 128 |
43 | //! | 80 | 1248 | 1248/160 | 160 |
44 | //! | 112 | 2432 | 2432/224 | 224 |
45 | //! | 128 | 3248 | 3248/256 | 256 |
46 | //! | 160 | 5312 | 5312/320 | 320 |
47 | //! | 192 | 7936 | 7936/384 | 384 |
48 | //! | 256 | 15424 | 15424/512 | 512 |
49 | //!
50 | //! # Security table
51 | //!
52 | //! Levels of security according to [ECRYPT II][ecrypt] [Yearly Report on Algorithms and
53 | //! Keysizes][d.spa.20]
54 | //!
55 | //! | Security Level | Security (bits) | Protection | Comment |
56 | //! | -------------- | --------------: | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
57 | //! | 1. | 32 | Attacks in "real-time" by individuals | Only acceptable for auth. tag size |
58 | //! | 2. | 64 | Very short-term protection against small organizations | Should not be used for confidentiality in new systems |
59 | //! | 3. | 72 | Short-term protection against medium organizations, mediumterm protection against small organizations | |
60 | //! | 4. | 80 | Very short-term protection against agencies, long-term prot. against small organizations | Smallest general-purpose level, <= 4 years protection |
61 | //! | 5. | 96 | Legacy standard level | 2-key 3DES restricted to ~10^6 plaintext/ciphertexts, ~10 years protection |
62 | //! | 6. | 112 | Medium-term protection | ~20 years protection |
63 | //! | 7. | 128 | Long-term protection | Good, generic application-indep. recommendation, ~30 years protection |
64 | //! | 8. | 256 | "Foreseeable future" | Good protection against quantum computers unless Shor's algorithm applies |
65 | //!
66 | //! We recommend at least 128-bit security for general purpose.
67 | //!
68 | //! [ecrypt]: http://www.ecrypt.eu.org/ "European Network of Excellence in Cryptology II "
69 | //! [d.spa.20]: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf "ECRYPT II Yearly Report on Algorithms and Keysizes"
70 |
71 | #![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
72 | html_root_url = "http://libOctavo.github.io/")]
73 |
74 | #![allow(many_single_char_names)]
75 |
76 | extern crate byteorder;
77 | extern crate generic_array;
78 | extern crate num_bigint as bigint;
79 | extern crate num_traits as num;
80 | extern crate num_integer as integer;
81 | extern crate rand;
82 | extern crate typenum;
83 |
84 | pub mod block;
85 | pub mod stream;
86 | pub mod asymmetric;
87 |
88 | pub mod prelude {
89 | pub use block::{BlockEncrypt, BlockDecrypt};
90 | pub use stream::{StreamEncrypt, StreamDecrypt};
91 | }
92 |
--------------------------------------------------------------------------------
/crypto/src/stream/chacha20.rs:
--------------------------------------------------------------------------------
1 | use std::slice;
2 |
3 | use super::{StreamEncrypt, StreamDecrypt};
4 |
5 | use byteorder::{ByteOrder, LittleEndian};
6 |
7 | const ROUNDS: usize = 20;
8 | const STATE_WORDS: usize = 16;
9 | const STATE_BYTES: usize = STATE_WORDS * 4;
10 |
11 | #[derive(Copy, Clone)]
12 | struct State([u32; STATE_WORDS]);
13 |
14 | macro_rules! quarter_round {
15 | ($a:expr, $b:expr, $c:expr, $d:expr) => {{
16 | $a = $a.wrapping_add($b); $d ^= $a; $d = $d.rotate_left(16);
17 | $c = $c.wrapping_add($d); $b ^= $c; $b = $b.rotate_left(12);
18 | $a = $a.wrapping_add($b); $d ^= $a; $d = $d.rotate_left( 8);
19 | $c = $c.wrapping_add($d); $b ^= $c; $b = $b.rotate_left( 7);
20 | }}
21 | }
22 |
23 | macro_rules! double_round {
24 | ($x:expr) => {{
25 | // Column round
26 | quarter_round!($x[ 0], $x[ 4], $x[ 8], $x[12]);
27 | quarter_round!($x[ 1], $x[ 5], $x[ 9], $x[13]);
28 | quarter_round!($x[ 2], $x[ 6], $x[10], $x[14]);
29 | quarter_round!($x[ 3], $x[ 7], $x[11], $x[15]);
30 | // Diagonal round
31 | quarter_round!($x[ 0], $x[ 5], $x[10], $x[15]);
32 | quarter_round!($x[ 1], $x[ 6], $x[11], $x[12]);
33 | quarter_round!($x[ 2], $x[ 7], $x[ 8], $x[13]);
34 | quarter_round!($x[ 3], $x[ 4], $x[ 9], $x[14]);
35 | }}
36 | }
37 |
38 | impl State {
39 | fn expand(key: &[u8], nonce: &[u8], position: u32) -> Self {
40 | let mut state = [0u32; STATE_WORDS];
41 |
42 | state[0] = 0x61707865;
43 | state[1] = 0x3320646e;
44 | state[2] = 0x79622d32;
45 | state[3] = 0x6b206574;
46 |
47 | for (state, chunk) in state[4..12].iter_mut().zip(key.chunks(4)) {
48 | *state = LittleEndian::read_u32(chunk);
49 | }
50 |
51 | state[12] = position;
52 |
53 | for (state, chunk) in state[13..16].iter_mut().zip(nonce.chunks(4)) {
54 | *state = LittleEndian::read_u32(chunk);
55 | }
56 |
57 | State(state)
58 | }
59 |
60 | fn update(&mut self, output: &mut [u32]) {
61 | let mut state = self.0;
62 |
63 | for _ in 0..ROUNDS / 2 {
64 | double_round!(state);
65 | }
66 |
67 | for i in 0..STATE_WORDS {
68 | output[i] = self.0[i].wrapping_add(state[i]);
69 | }
70 |
71 | self.0[12] += 1;
72 | }
73 | }
74 |
75 | pub struct ChaCha20 {
76 | state: State,
77 | buffer: [u32; STATE_WORDS],
78 | index: usize,
79 | }
80 |
81 | impl ChaCha20 {
82 | pub fn init(key: &[u8], nonce: &[u8], position: u32) -> Self {
83 | ChaCha20 {
84 | state: State::expand(key.as_ref(), nonce.as_ref(), position),
85 | buffer: [0; STATE_WORDS],
86 | index: STATE_BYTES,
87 | }
88 | }
89 |
90 | pub fn new(key: Key, nonce: Nonce) -> Self
91 | where Key: AsRef<[u8]>,
92 | Nonce: AsRef<[u8]>
93 | {
94 | Self::init(key.as_ref(), nonce.as_ref(), 1)
95 | }
96 |
97 | fn update(&mut self) {
98 | self.state.update(&mut self.buffer[..]);
99 |
100 | self.index = 0;
101 | }
102 |
103 | fn crypt(&mut self, input: &[u8], output: &mut [u8]) {
104 | if self.index == STATE_BYTES {
105 | self.update()
106 | }
107 |
108 | let buffer = unsafe {
109 | slice::from_raw_parts(self.buffer.as_ptr() as *const u8, STATE_BYTES)
110 | };
111 |
112 | for i in self.index..input.len() {
113 | output[i] = input[i] ^ buffer[i];
114 | }
115 |
116 | self.index = input.len();
117 | }
118 | }
119 |
120 | impl StreamEncrypt for ChaCha20 {
121 | fn encrypt_stream(&mut self, input: I, mut output: O)
122 | where I: AsRef<[u8]>,
123 | O: AsMut<[u8]>
124 | {
125 | assert_eq!(input.as_ref().len(), output.as_mut().len());
126 | let input = input.as_ref();
127 | let output = output.as_mut();
128 |
129 | let from = STATE_BYTES - self.index;
130 |
131 | if from > 0 {
132 | self.crypt(&input[..from], &mut output[..from]);
133 | }
134 |
135 | for (i, o) in input[from..]
136 | .chunks(STATE_BYTES)
137 | .zip(output[from..].chunks_mut(STATE_BYTES)) {
138 | self.crypt(i, o)
139 | }
140 | }
141 | }
142 |
143 | impl StreamDecrypt for ChaCha20 {
144 | fn decrypt_stream(&mut self, input: I, mut output: O)
145 | where I: AsRef<[u8]>,
146 | O: AsMut<[u8]>
147 | {
148 | assert_eq!(input.as_ref().len(), output.as_mut().len());
149 |
150 | let input = input.as_ref().chunks(STATE_BYTES);
151 | let output = output.as_mut().chunks_mut(STATE_BYTES);
152 | for (i, o) in input.zip(output) {
153 | self.crypt(i, o)
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/crypto/src/stream/mod.rs:
--------------------------------------------------------------------------------
1 | //! Stream cryptosystems
2 |
3 | pub mod chacha20;
4 |
5 | pub trait StreamEncrypt {
6 | fn encrypt_stream(&mut self, input: I, output: O)
7 | where I: AsRef<[u8]>,
8 | O: AsMut<[u8]>;
9 | }
10 |
11 | pub trait StreamDecrypt {
12 | fn decrypt_stream(&mut self, input: I, output: O)
13 | where I: AsRef<[u8]>,
14 | O: AsMut<[u8]>;
15 | }
16 |
--------------------------------------------------------------------------------
/crypto/tests/asymmetric/dh/mod.rs:
--------------------------------------------------------------------------------
1 | use crypto::asymmetric::dh::{DHParameters, RFC2409_PRIME_768, RFC2409_GENERATOR_768,
2 | RFC2409_PRIME_1024, RFC2409_GENERATOR_1024};
3 |
4 |
5 | fn test_exhange_with_params(params: &DHParameters) {
6 | let priv_key1 = params.private_key();
7 | let priv_key2 = params.private_key();
8 | let pub_key1 = priv_key1.public_key();
9 | let pub_key2 = priv_key2.public_key();
10 | let shared_key1 = priv_key2.exchange(&pub_key1);
11 | let shared_key2 = priv_key1.exchange(&pub_key2);
12 | assert!(shared_key1 == shared_key2);
13 | }
14 |
15 | #[test]
16 | fn test_exchange() {
17 | test_exhange_with_params(&DHParameters::new(&[0x17], 5));
18 | test_exhange_with_params(&DHParameters::new(&RFC2409_PRIME_768, RFC2409_GENERATOR_768));
19 | test_exhange_with_params(&DHParameters::new(&RFC2409_PRIME_1024, RFC2409_GENERATOR_1024));
20 | }
21 |
--------------------------------------------------------------------------------
/crypto/tests/asymmetric/mod.rs:
--------------------------------------------------------------------------------
1 | mod dh;
2 |
--------------------------------------------------------------------------------
/crypto/tests/asymmetric/rsa/mod.rs:
--------------------------------------------------------------------------------
1 | use crypto::asymmetric::rsa::Rsa;
2 |
3 | use num::bigint::ToBigUint;
4 |
5 | fn keys() -> (Rsa, Rsa) {
6 | Rsa::keypair_from_primes(61.to_biguint().unwrap(),
7 | 53.to_biguint().unwrap(),
8 | 17.to_biguint().unwrap())
9 | }
10 |
11 | #[test]
12 | fn encryption() {
13 | let (public, _) = keys();
14 | let c = public.crypt(&65.to_biguint().unwrap());
15 |
16 | assert_eq!(c, 2790.to_biguint().unwrap())
17 | }
18 |
19 | #[test]
20 | fn decryption() {
21 | let (_, private) = keys();
22 | let m = private.crypt(&2790.to_biguint().unwrap());
23 |
24 | assert_eq!(m, 65.to_biguint().unwrap())
25 | }
26 |
--------------------------------------------------------------------------------
/crypto/tests/block/blowfish.rs:
--------------------------------------------------------------------------------
1 | use crypto::block::blowfish::Blowfish;
2 | use crypto::block::{BlockEncrypt, BlockDecrypt};
3 |
4 | struct Test {
5 | key: [u8; 8],
6 | plaintext: [u8; 8],
7 | ciphertext: [u8; 8],
8 | }
9 |
10 | const TESTS: [Test; 33] = [Test {
11 | key: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
12 | plaintext: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
13 | ciphertext: [0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78],
14 | },
15 | Test {
16 | key: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
17 | plaintext: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
18 | ciphertext: [0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A],
19 | },
20 | Test {
21 | key: [0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
22 | plaintext: [0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
23 | ciphertext: [0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2],
24 | },
25 | Test {
26 | key: [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11],
27 | plaintext: [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11],
28 | ciphertext: [0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D],
29 | },
30 | Test {
31 | key: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
32 | plaintext: [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11],
33 | ciphertext: [0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96],
34 | },
35 | Test {
36 | key: [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11],
37 | plaintext: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
38 | ciphertext: [0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7],
39 | },
40 | Test {
41 | key: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10],
42 | plaintext: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
43 | ciphertext: [0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D],
44 | },
45 | Test {
46 | key: [0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57],
47 | plaintext: [0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42],
48 | ciphertext: [0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B],
49 | },
50 | Test {
51 | key: [0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E],
52 | plaintext: [0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA],
53 | ciphertext: [0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0],
54 | },
55 | Test {
56 | key: [0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86],
57 | plaintext: [0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72],
58 | ciphertext: [0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4],
59 | },
60 | Test {
61 | key: [0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E],
62 | plaintext: [0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A],
63 | ciphertext: [0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB],
64 | },
65 | Test {
66 | key: [0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6],
67 | plaintext: [0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2],
68 | ciphertext: [0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A],
69 | },
70 | Test {
71 | key: [0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE],
72 | plaintext: [0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A],
73 | ciphertext: [0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18],
74 | },
75 | Test {
76 | key: [0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6],
77 | plaintext: [0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2],
78 | ciphertext: [0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98],
79 | },
80 | Test {
81 | key: [0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE],
82 | plaintext: [0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A],
83 | ciphertext: [0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5],
84 | },
85 | Test {
86 | key: [0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16],
87 | plaintext: [0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02],
88 | ciphertext: [0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79],
89 | },
90 | Test {
91 | key: [0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F],
92 | plaintext: [0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A],
93 | ciphertext: [0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3],
94 | },
95 | Test {
96 | key: [0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46],
97 | plaintext: [0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32],
98 | ciphertext: [0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69],
99 | },
100 | Test {
101 | key: [0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E],
102 | plaintext: [0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA],
103 | ciphertext: [0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B],
104 | },
105 | Test {
106 | key: [0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76],
107 | plaintext: [0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62],
108 | ciphertext: [0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E],
109 | },
110 | Test {
111 | key: [0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07],
112 | plaintext: [0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2],
113 | ciphertext: [0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD],
114 | },
115 | Test {
116 | key: [0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F],
117 | plaintext: [0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA],
118 | ciphertext: [0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19],
119 | },
120 | Test {
121 | key: [0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7],
122 | plaintext: [0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92],
123 | ciphertext: [0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3],
124 | },
125 | Test {
126 | key: [0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF],
127 | plaintext: [0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A],
128 | ciphertext: [0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5],
129 | },
130 | Test {
131 | key: [0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6],
132 | plaintext: [0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2],
133 | ciphertext: [0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78],
134 | },
135 | Test {
136 | key: [0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF],
137 | plaintext: [0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A],
138 | ciphertext: [0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01],
139 | },
140 | Test {
141 | key: [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01],
142 | plaintext: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
143 | ciphertext: [0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2],
144 | },
145 | Test {
146 | key: [0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E],
147 | plaintext: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
148 | ciphertext: [0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE],
149 | },
150 | Test {
151 | key: [0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE],
152 | plaintext: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
153 | ciphertext: [0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D],
154 | },
155 | Test {
156 | key: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
157 | plaintext: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
158 | ciphertext: [0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4],
159 | },
160 | Test {
161 | key: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
162 | plaintext: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
163 | ciphertext: [0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC],
164 | },
165 | Test {
166 | key: [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF],
167 | plaintext: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
168 | ciphertext: [0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A],
169 | },
170 | Test {
171 | key: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10],
172 | plaintext: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
173 | ciphertext: [0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A],
174 | }];
175 |
176 | #[test]
177 | fn base_case() {
178 | let b = Blowfish::init();
179 | let data = [6; 8];
180 | let mut crypto = [0; 8];
181 | let mut result = [0; 8];
182 |
183 | b.encrypt_block(data, &mut crypto);
184 | b.decrypt_block(crypto, &mut result);
185 | assert_eq!(result, data);
186 | }
187 |
188 | #[test]
189 | fn base_test_vectors() {
190 | for test in TESTS.iter() {
191 | let c = Blowfish::new(test.key);
192 | let mut dat = [0; 8];
193 |
194 | c.encrypt_block(test.plaintext, &mut dat);
195 | assert_eq!(test.ciphertext, dat);
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/crypto/tests/block/mod.rs:
--------------------------------------------------------------------------------
1 | mod blowfish;
2 |
--------------------------------------------------------------------------------
/crypto/tests/lib.rs:
--------------------------------------------------------------------------------
1 | extern crate octavo_crypto as crypto;
2 |
3 | mod block;
4 | mod stream;
5 | mod asymmetric;
6 |
--------------------------------------------------------------------------------
/crypto/tests/stream/chacha20.rs:
--------------------------------------------------------------------------------
1 | use crypto::stream::chacha20::ChaCha20;
2 | use crypto::stream::{StreamEncrypt, StreamDecrypt};
3 |
4 | struct Test<'a> {
5 | key: [u8; 32],
6 | nonce: [u8; 12],
7 | position: u32,
8 | plaintext: &'a [u8],
9 | ciphertext: &'a [u8],
10 | }
11 |
12 | const TESTS: [Test<'static>; 2] = [
13 | Test {
14 | key: [
15 | 0, 0, 0, 0, 0, 0, 0, 0,
16 | 0, 0, 0, 0, 0, 0, 0, 0,
17 | 0, 0, 0, 0, 0, 0, 0, 0,
18 | 0, 0, 0, 0, 0, 0, 0, 0,
19 | ],
20 | nonce: [
21 | 0, 0, 0, 0, 0, 0,
22 | 0, 0, 0, 0, 0, 0,
23 | ],
24 | position: 0,
25 | plaintext: &[0; 64],
26 | ciphertext: &[
27 | 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
28 | 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
29 | 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
30 | 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
31 | ]
32 | },
33 | Test {
34 | key: [
35 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
36 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
37 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
38 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
39 | ],
40 | nonce: [
41 | 0, 0, 0, 0, 0, 0,
42 | 0, 0x4a, 0, 0, 0, 0,
43 | ],
44 | position: 1,
45 | plaintext: b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.",
46 | ciphertext: &[
47 | 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81,
48 | 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b,
49 | 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57,
50 | 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8,
51 | 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d, 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e,
52 | 0x52, 0xbc, 0x51, 0x4d, 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36,
53 | 0x5a, 0xf9, 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42,
54 | 0x87, 0x4d,
55 | ]
56 | }
57 | ];
58 |
59 | #[test]
60 | fn encryption() {
61 | for test in &TESTS {
62 | let mut cipher = ChaCha20::init(&test.key[..], &test.nonce[..], test.position);
63 | let mut buf = vec![0; test.plaintext.len()];
64 |
65 | cipher.encrypt_stream(test.plaintext, &mut buf[..]);
66 | assert_eq!(test.ciphertext, &buf[..]);
67 | }
68 | }
69 |
70 | #[test]
71 | fn decryption() {
72 | for test in &TESTS {
73 | let mut cipher = ChaCha20::init(&test.key[..], &test.nonce[..], test.position);
74 | let mut buf = vec![0; test.plaintext.len()];
75 |
76 | cipher.decrypt_stream(test.ciphertext, &mut buf[..]);
77 | assert_eq!(test.plaintext, &buf[..]);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/crypto/tests/stream/mod.rs:
--------------------------------------------------------------------------------
1 | mod chacha20;
2 |
--------------------------------------------------------------------------------
/digest/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ["Łukasz Jan Niemier "]
3 | homepage = "http://liboctavo.github.io/"
4 | documentation = "http://liboctavo.github.io/octavo/octavo_digest"
5 | repository = "https://github.com/libOctavo/octavo"
6 | readme = "README.md"
7 | name = "octavo-digest"
8 | description = "Octavo - Cryptographic Hash Functions. WARNING!!! Not suitable for production"
9 | keywords = [
10 | "md5", "sha", "sha1", "sha2", "sha3", "tiger", "blake2", "hash", "ripemd"
11 | ]
12 | license = "MIT"
13 | version = "0.1.2"
14 |
15 | [profile.bench]
16 | debug = true
17 | lto = true
18 |
19 | [profile.release]
20 | lto = true
21 | opt-level = 3
22 |
23 | [dependencies]
24 | generic-array = "0.2.0"
25 | static-buffer = "0.2.0"
26 | typenum = "1.2.0"
27 |
28 | [dependencies.byteorder]
29 | version = "0.5"
30 | default-features = false
31 |
32 | [dev-dependencies]
33 | rustc-serialize = "0.3.16"
34 | toml = "0.1.27"
35 |
36 | [features]
37 | default = ["all"]
38 | unstable = []
39 |
40 | all = ["md5", "ripemd", "sha1", "sha2", "sha3", "tiger", "blake2", "whirlpool"]
41 | safe = ["blake2", "sha2", "sha3", "tiger"]
42 | deprecated = ["md5", "ripemd", "sha1"]
43 |
44 | blake2 = []
45 | md5 = []
46 | ripemd = []
47 | sha1 = []
48 | sha2 = []
49 | sha3 = []
50 | tiger = []
51 | whirlpool = []
52 |
--------------------------------------------------------------------------------
/digest/benches/blake2/mod.rs:
--------------------------------------------------------------------------------
1 | mod blake2s {
2 | use test::Bencher;
3 |
4 | use digest::blake2::Blake2s256;
5 |
6 | bench_digest!(Blake2s256);
7 | }
8 |
9 | mod blake2b {
10 | use test::Bencher;
11 |
12 | use digest::blake2::Blake2b512;
13 |
14 | bench_digest!(Blake2b512);
15 | }
16 |
--------------------------------------------------------------------------------
/digest/benches/lib.rs:
--------------------------------------------------------------------------------
1 | #![feature(test)]
2 |
3 | extern crate octavo_digest as digest;
4 | extern crate test;
5 |
6 | #[macro_export]
7 | macro_rules! bench_digest {
8 | ($name:ident, $engine:path, $bs:expr) => {
9 | #[bench]
10 | fn $name(b: &mut Bencher) {
11 | use digest::Digest;
12 |
13 | let mut d = <$engine>::default();
14 | let data = vec![0; $bs];
15 |
16 | b.iter(|| {
17 | d.update(&data);
18 | });
19 |
20 | b.bytes = $bs;
21 | }
22 | };
23 |
24 | ($engine:path) => {
25 | bench_digest!(_16_block_size, $engine, 16);
26 | bench_digest!(_64_block_size, $engine, 64);
27 | bench_digest!(_256_block_size, $engine, 256);
28 | bench_digest!(_1k_block_size, $engine, 1024);
29 | bench_digest!(_8k_block_size, $engine, 8192);
30 | bench_digest!(_64k_block_size, $engine, 65536);
31 | }
32 | }
33 |
34 | #[cfg(feature = "md5")] #[macro_use]mod md5;
35 | #[cfg(feature = "sha1")] #[macro_use]mod sha1;
36 | #[cfg(feature = "sha2")] #[macro_use]mod sha2;
37 | #[cfg(feature = "sha3")] #[macro_use]mod sha3;
38 | #[cfg(feature = "tiger")] #[macro_use]mod tiger;
39 | #[cfg(feature = "ripemd")] #[macro_use]mod ripemd;
40 | #[cfg(feature = "blake2")] #[macro_use]mod blake2;
41 | #[cfg(feature = "whirlpool")] #[macro_use]mod whirlpool;
42 |
--------------------------------------------------------------------------------
/digest/benches/md5/mod.rs:
--------------------------------------------------------------------------------
1 | use test::Bencher;
2 |
3 | use digest::md5::Md5;
4 |
5 | bench_digest!(Md5);
6 |
--------------------------------------------------------------------------------
/digest/benches/ripemd/mod.rs:
--------------------------------------------------------------------------------
1 | use test::Bencher;
2 |
3 | use digest::ripemd::Ripemd160;
4 |
5 | bench_digest!(Ripemd160);
6 |
--------------------------------------------------------------------------------
/digest/benches/sha1/mod.rs:
--------------------------------------------------------------------------------
1 | use test::Bencher;
2 |
3 | use digest::sha1::Sha1;
4 |
5 | bench_digest!(Sha1);
6 |
--------------------------------------------------------------------------------
/digest/benches/sha2/mod.rs:
--------------------------------------------------------------------------------
1 | mod sha224 {
2 | use test::Bencher;
3 |
4 | use digest::sha2;
5 |
6 | bench_digest!(sha2::Sha224);
7 | }
8 |
9 | mod sha256 {
10 | use test::Bencher;
11 |
12 | use digest::sha2;
13 |
14 | bench_digest!(sha2::Sha256);
15 | }
16 |
17 | mod sha384 {
18 | use test::Bencher;
19 |
20 | use digest::sha2;
21 |
22 | bench_digest!(sha2::Sha384);
23 | }
24 |
25 | mod sha512 {
26 | use test::Bencher;
27 |
28 | use digest::sha2;
29 |
30 | bench_digest!(sha2::Sha512);
31 | }
32 |
--------------------------------------------------------------------------------
/digest/benches/sha3/mod.rs:
--------------------------------------------------------------------------------
1 | mod sha224 {
2 | use test::Bencher;
3 |
4 | use digest::sha3;
5 |
6 | bench_digest!(sha3::Sha224);
7 | }
8 |
9 | mod sha256 {
10 | use test::Bencher;
11 |
12 | use digest::sha3;
13 |
14 | bench_digest!(sha3::Sha256);
15 | }
16 |
17 | mod sha384 {
18 | use test::Bencher;
19 |
20 | use digest::sha3;
21 |
22 | bench_digest!(sha3::Sha384);
23 | }
24 |
25 | mod sha512 {
26 | use test::Bencher;
27 |
28 | use digest::sha3;
29 |
30 | bench_digest!(sha3::Sha512);
31 | }
32 |
--------------------------------------------------------------------------------
/digest/benches/tiger/mod.rs:
--------------------------------------------------------------------------------
1 | mod tiger {
2 | use test::Bencher;
3 |
4 | use digest::tiger::Tiger;
5 |
6 | bench_digest!(Tiger);
7 | }
8 |
9 | mod tiger2 {
10 | use test::Bencher;
11 |
12 | use digest::tiger::Tiger2;
13 |
14 | bench_digest!(Tiger2);
15 | }
16 |
--------------------------------------------------------------------------------
/digest/benches/whirlpool/mod.rs:
--------------------------------------------------------------------------------
1 | use test::Bencher;
2 |
3 | use digest::whirlpool::Whirlpool;
4 |
5 | bench_digest!(Whirlpool);
6 |
--------------------------------------------------------------------------------
/digest/src/blake2/mod.rs:
--------------------------------------------------------------------------------
1 | //! BLAKE2 family
2 | //!
3 | //! # General info
4 | //!
5 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
6 | //! | ----------- | ----------: | ---------: | -----: | -------------------- | ----------------------- |
7 | //! | BLAKE2s-128 | 128 bits | 512 bits | 10 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
8 | //! | BLAKE2s-160 | 160 bits | 512 bits | 10 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
9 | //! | BLAKE2s-224 | 224 bits | 512 bits | 10 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
10 | //! | BLAKE2s-256 | 256 bits | 512 bits | 10 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
11 | //! | BLAKE2b-160 | 160 bits | 1024 bits | 12 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
12 | //! | BLAKE2b-256 | 256 bits | 1024 bits | 12 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
13 | //! | BLAKE2b-384 | 384 bits | 1024 bits | 12 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
14 | //! | BLAKE2b-512 | 512 bits | 1024 bits | 12 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
15 | //!
16 | //! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction
17 |
18 | #![allow(doc_markdown)]
19 |
20 | use core::marker::PhantomData;
21 | use core::ptr;
22 | use core::ops::Mul;
23 |
24 | use static_buffer::{FixedBuffer64, FixedBuffer128, FixedBuf};
25 | use byteorder::{ByteOrder, LittleEndian};
26 | use generic_array::ArrayLength;
27 | use typenum::uint::Unsigned;
28 | use typenum::consts::{U8, U16, U20, U28, U32, U48, U64, U128};
29 |
30 | use Digest;
31 | use wrapping::*;
32 |
33 | const BLAKE2S_INIT: [w32; 8] = [W(0x6a09e667),
34 | W(0xbb67ae85),
35 | W(0x3c6ef372),
36 | W(0xa54ff53a),
37 | W(0x510e527f),
38 | W(0x9b05688c),
39 | W(0x1f83d9ab),
40 | W(0x5be0cd19)];
41 | const BLAKE2B_INIT: [w64; 8] = [W(0x6a09e667f3bcc908),
42 | W(0xbb67ae8584caa73b),
43 | W(0x3c6ef372fe94f82b),
44 | W(0xa54ff53a5f1d36f1),
45 | W(0x510e527fade682d1),
46 | W(0x9b05688c2b3e6c1f),
47 | W(0x1f83d9abfb41bd6b),
48 | W(0x5be0cd19137e2179)];
49 |
50 | const SIGMA: [[usize; 16]; 12] = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
51 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
52 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
53 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
54 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
55 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
56 | [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
57 | [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
58 | [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
59 | [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
60 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
61 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3]];
62 |
63 | macro_rules! G {
64 | ($v:ident, $a:expr, $b:expr, $c:expr, $d:expr, $x:expr, $y:expr) => {
65 | $v[$a] += $v[$b] + $x;
66 | $v[$d] = ($v[$d] ^ $v[$a]).rotate_right(R1);
67 | $v[$c] += $v[$d];
68 | $v[$b] = ($v[$b] ^ $v[$c]).rotate_right(R2);
69 | $v[$a] += $v[$b] + $y;
70 | $v[$d] = ($v[$d] ^ $v[$a]).rotate_right(R3);
71 | $v[$c] += $v[$d];
72 | $v[$b] = ($v[$b] ^ $v[$c]).rotate_right(R4);
73 | }
74 | }
75 |
76 | #[derive(Copy, Clone, Debug)]
77 | struct State {
78 | h: [W; 8],
79 | }
80 |
81 | macro_rules! blake2_state {
82 | ($word:ty, $read:ident, $init:ident, $rounds:expr, $r1:expr, $r2:expr, $r3:expr, $r4:expr) => {
83 | impl State<$word> {
84 | fn new(key_size: u8, size: u8) -> Self {
85 | let mut state = $init;
86 |
87 | state[0] ^= W(0x01010000 ^ ((key_size as $word) << 8) ^ (size as $word));
88 |
89 | State { h: state }
90 | }
91 |
92 | #[inline]
93 | fn compress(&mut self, input: &[u8], len: Length<$word>, last: bool) {
94 | debug_assert!(input.len() % 16 == 0);
95 | const R1: u32 = $r1;
96 | const R2: u32 = $r2;
97 | const R3: u32 = $r3;
98 | const R4: u32 = $r4;
99 |
100 | let mut message = [W(0); 16];
101 | for (word, chunk) in message.iter_mut().zip(input.chunks(input.len() / 16)) {
102 | *word = W(LittleEndian::$read(chunk));
103 | }
104 |
105 | let mut v = [W(0); 16];
106 | for (v, state) in v.iter_mut().zip(self.h.iter().chain(&$init)) {
107 | *v = *state;
108 | }
109 | v[12].0 ^= len.0.to_le();
110 | v[13].0 ^= len.1.to_le();
111 | if last {
112 | v[14] = !v[14];
113 | }
114 |
115 | for sigma in &SIGMA[..$rounds] {
116 | G!(v, 0, 4, 8, 12, message[sigma[0]], message[sigma[1]]);
117 | G!(v, 1, 5, 9, 13, message[sigma[2]], message[sigma[3]]);
118 | G!(v, 2, 6, 10, 14, message[sigma[4]], message[sigma[5]]);
119 | G!(v, 3, 7, 11, 15, message[sigma[6]], message[sigma[7]]);
120 |
121 | G!(v, 0, 5, 10, 15, message[sigma[8]], message[sigma[9]]);
122 | G!(v, 1, 6, 11, 12, message[sigma[10]], message[sigma[11]]);
123 | G!(v, 2, 7, 8, 13, message[sigma[12]], message[sigma[13]]);
124 | G!(v, 3, 4, 9, 14, message[sigma[14]], message[sigma[15]]);
125 | }
126 |
127 | let (head, tail) = v.split_at(8);
128 | let vs = head.iter().zip(tail);
129 |
130 | for (h, (&v1, &v2)) in self.h.iter_mut().zip(vs) {
131 | *h ^= v1 ^ v2;
132 | }
133 | }
134 | }
135 | }
136 | }
137 |
138 | blake2_state!(u32, read_u32, BLAKE2S_INIT, 10, 16, 12, 8, 7);
139 | blake2_state!(u64, read_u64, BLAKE2B_INIT, 12, 32, 24, 16, 63);
140 |
141 | #[derive(Copy, Clone, Debug)]
142 | struct Length(T, T);
143 |
144 | impl Length {
145 | fn increment(&mut self, val: usize) {
146 | self.0 = self.0.wrapping_add(val as u32);
147 | }
148 | }
149 |
150 | impl Length {
151 | fn increment(&mut self, val: usize) {
152 | self.0 = self.0.wrapping_add(val as u64);
153 | }
154 | }
155 |
156 | macro_rules! blake2 {
157 | ($(#[$attr:meta])* struct $name:ident<$word:ty>, $buf:ty, $bsize:ty, $wsize: expr) => {
158 | #[derive(Clone)]
159 | $(#[$attr])*
160 | pub struct $name {
161 | state: State<$word>,
162 | len: Length<$word>,
163 | buffer: $buf,
164 | _phantom: PhantomData,
165 | }
166 |
167 | impl $name
168 | where Size: Unsigned + Clone + ArrayLength + Mul,
169 | >::Output: ArrayLength
170 | {
171 | /// Default
172 | pub fn default() -> Self {
173 | Self::with_key(&[])
174 | }
175 |
176 | /// Initialize BLAKE2 hash function with custom key
177 | pub fn with_key>(key: K) -> Self {
178 | let key = key.as_ref();
179 |
180 | assert!(key.len() <= $wsize);
181 |
182 | let mut ret = $name {
183 | state: State::<$word>::new(key.len() as u8, Size::to_u8()),
184 | len: Length(0, 0),
185 | buffer: <$buf>::new(),
186 | _phantom: PhantomData
187 | };
188 |
189 | if !key.is_empty() {
190 | ret.update(key);
191 | ret.buffer.zero_until(<$buf>::size());
192 | }
193 |
194 | ret
195 | }
196 | }
197 |
198 | impl Digest for $name
199 | where Size: ArrayLength + Mul + Clone,
200 | >::Output: ArrayLength
201 | {
202 | type OutputBits = >::Output;
203 | type OutputBytes = Size;
204 | type BlockSize = $bsize;
205 |
206 | fn update>(&mut self, input: T) {
207 | let input = input.as_ref();
208 |
209 | let state = &mut self.state;
210 | let len = &mut self.len;
211 |
212 | self.buffer.input(input, |d| {
213 | len.increment(d.len());
214 | state.compress(d, *len, false);
215 | })
216 | }
217 |
218 | fn result>(mut self, mut out: T) {
219 | let rest = self.buffer.position();
220 | self.len.increment(rest);
221 | self.buffer.zero_until(<$buf>::size());
222 |
223 | self.state.compress(self.buffer.full_buffer(), self.len, true);
224 |
225 | let mut out = out.as_mut();
226 | assert!(out.len() >= Self::output_bytes());
227 |
228 | unsafe {
229 | ptr::copy_nonoverlapping(self.state.h.as_ptr() as *const u8,
230 | out.as_mut_ptr(),
231 | Self::output_bytes())
232 | }
233 | }
234 | }
235 | }
236 | }
237 |
238 | blake2! {
239 | /// General BLAKE2s implementation
240 | struct Blake2s, FixedBuffer64, U64, 32
241 | }
242 | blake2! {
243 | /// General BLAKE2b implementation
244 | struct Blake2b, FixedBuffer128, U128, 64
245 | }
246 |
247 | /// BLAKE2s-128 implementation
248 | pub type Blake2s128 = Blake2s;
249 | /// BLAKE2s-160 implementation
250 | pub type Blake2s160 = Blake2s;
251 | /// BLAKE2s-224 implementation
252 | pub type Blake2s224 = Blake2s;
253 | /// BLAKE2s-256 implementation
254 | pub type Blake2s256 = Blake2s;
255 |
256 | /// BLAKE2b-160 implementation
257 | pub type Blake2b160 = Blake2b;
258 | /// BLAKE2b-256 implementation
259 | pub type Blake2b256 = Blake2b;
260 | /// BLAKE2b-384 implementation
261 | pub type Blake2b384 = Blake2b;
262 | /// BLAKE2b-512 implementation
263 | pub type Blake2b512 = Blake2b;
264 |
--------------------------------------------------------------------------------
/digest/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! Cryptographic hash functions primitives
2 | //!
3 | //! Via [Wikipedia](https://en.wikipedia.org/wiki/Cryptographic_hash_function):
4 | //!
5 | //! > The ideal cryptographic hash function has four main properties:
6 | //! >
7 | //! > - it is easy to compute the hash value for any given message
8 | //! > - it is infeasible to generate a message from its hash
9 | //! > - it is infeasible to modify a message without changing the hash
10 | //! > - it is infeasible to find two different messages with the same hash.
11 | //!
12 | //! # Example
13 | //!
14 | //! Calculate SHA-512 sum:
15 | //!
16 | //! ```rust
17 | //! # extern crate octavo_digest;
18 | //! use octavo_digest::prelude::*;
19 | //!
20 | //! # fn main() {
21 | //! # let data = "Hello World!";
22 | //! let mut result = vec![0; sha2::Sha512::output_bytes()];
23 | //! let mut sha = sha2::Sha512::default();
24 | //!
25 | //! sha.update(data);
26 | //! sha.result(&mut result);
27 | //!
28 | //! for byte in result {
29 | //! print!("{:2x}", byte);
30 | //! }
31 | //! println!(" {}", data);
32 | //! # }
33 | //! ```
34 |
35 | #![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
36 | html_root_url = "http://libOctavo.github.io/")]
37 |
38 | #![no_std]
39 |
40 | #![allow(inline_always, unknown_lints)]
41 | #![forbid(overflowing_literals, missing_docs)]
42 |
43 | extern crate generic_array;
44 | extern crate static_buffer;
45 | extern crate typenum;
46 | extern crate byteorder;
47 |
48 | use generic_array::ArrayLength;
49 | use typenum::uint::Unsigned;
50 |
51 | /// Hash function digest definition
52 | pub trait Digest: Clone {
53 | /// Output size in bits
54 | type OutputBits: Unsigned + ArrayLength;
55 | /// Output size in bytes
56 | type OutputBytes: Unsigned + ArrayLength;
57 |
58 | /// Block size in bytes
59 | type BlockSize: Unsigned + ArrayLength;
60 |
61 | /// Update digest with data.
62 | fn update(&mut self, input: T) where T: AsRef<[u8]>;
63 |
64 | /// Output size in bits
65 | fn output_bits() -> usize {
66 | Self::OutputBits::to_usize()
67 | }
68 | /// Output size in bytes
69 | fn output_bytes() -> usize {
70 | Self::OutputBytes::to_usize()
71 | }
72 | /// Block size in bytes
73 | fn block_size() -> usize {
74 | Self::BlockSize::to_usize()
75 | }
76 |
77 | /// Write resulting hash into `output`.
78 | ///
79 | /// `output` should be big enough to contain whole output.
80 | ///
81 | /// ## Panics
82 | ///
83 | /// If output length is less than `Digest::output_bytes`.
84 | fn result(self, output: T) where T: AsMut<[u8]>;
85 | }
86 |
87 | /// Digest prelude
88 | pub mod prelude {
89 | pub use Digest;
90 |
91 | #[cfg(feature = "blake2")]
92 | pub use blake2;
93 | #[cfg(feature = "md5")]
94 | pub use md5::Md5;
95 | #[cfg(feature = "ripemd")]
96 | pub use ripemd::Ripemd160;
97 | #[cfg(feature = "sha1")]
98 | pub use sha1::Sha1;
99 | #[cfg(feature = "sha2")]
100 | pub use sha2;
101 | #[cfg(feature = "sha3")]
102 | pub use sha3;
103 | #[cfg(feature = "tiger")]
104 | pub use tiger;
105 | #[cfg(feature = "whirlpool")]
106 | pub use whirlpool::Whirlpool;
107 | }
108 |
109 | #[cfg(feature = "blake2")]
110 | pub mod blake2;
111 | #[cfg(feature = "md5")]
112 | pub mod md5;
113 | #[cfg(feature = "ripemd")]
114 | pub mod ripemd;
115 | #[cfg(feature = "sha1")]
116 | pub mod sha1;
117 | #[cfg(feature = "sha2")]
118 | pub mod sha2;
119 | #[cfg(feature = "sha3")]
120 | pub mod sha3;
121 | #[cfg(feature = "tiger")]
122 | pub mod tiger;
123 | #[cfg(feature = "whirlpool")]
124 | pub mod whirlpool;
125 |
126 | mod wrapping;
127 | mod simd;
128 |
--------------------------------------------------------------------------------
/digest/src/md5.rs:
--------------------------------------------------------------------------------
1 | //! MD5 (Message-Digest Algorithm version 5)
2 | //!
3 | //! # WARNING!!!
4 | //!
5 | //! This hash function has been severely compromised. **Do not use!**
6 | //!
7 | //! Instead you should use SHA-2 or SHA-3 family (if security required) or Tiger (if speed required).
8 | //!
9 | //! # General info
10 | //!
11 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
12 | //! | ---- | ----------: | ---------: | ------:| -------------------- | ------------------- |
13 | //! | MD5 | 128 bits | 512 bits | 4 | [Merkle–Damgård][md] | [RFC 1321][rfc1321] |
14 | //!
15 | //! [rfc1321]: https://tools.ietf.org/html/rfc1321 "The MD5 Message-Digest Algorithm"
16 | //! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction
17 |
18 | use byteorder::{ByteOrder, LittleEndian};
19 | use typenum::consts::{U16, U64, U128};
20 | use static_buffer::{FixedBuffer64, FixedBuf, StandardPadding};
21 |
22 | use Digest;
23 | use wrapping::*;
24 |
25 | #[derive(Copy, Clone, Debug)]
26 | struct State {
27 | a: w32,
28 | b: w32,
29 | c: w32,
30 | d: w32,
31 | }
32 |
33 | macro_rules! process {
34 | ($w:expr, $x:expr, $y:expr, $z:expr, $m:expr, $s:expr, $f:ident) => {
35 | $w = ($w + $f($x, $y, $z) + $m).rotate_left($s) + $x
36 | }
37 | }
38 |
39 | #[inline]
40 | fn f(u: w32, v: w32, w: w32) -> w32 {
41 | (u & v) | (!u & w)
42 | }
43 | #[inline]
44 | fn g(u: w32, v: w32, w: w32) -> w32 {
45 | (u & w) | (v & !w)
46 | }
47 | #[inline]
48 | fn h(u: w32, v: w32, w: w32) -> w32 {
49 | u ^ v ^ w
50 | }
51 | #[inline]
52 | fn i(u: w32, v: w32, w: w32) -> w32 {
53 | v ^ (u | !w)
54 | }
55 |
56 | impl State {
57 | fn new() -> Self {
58 | State {
59 | a: W(0x67452301),
60 | b: W(0xefcdab89),
61 | c: W(0x98badcfe),
62 | d: W(0x10325476),
63 | }
64 | }
65 |
66 | #[inline]
67 | fn compress(&mut self, input: &[u8]) {
68 | let State { mut a, mut b, mut c, mut d } = *self;
69 |
70 | let mut data = [W(0); 16];
71 |
72 | for (v, c) in data.iter_mut().zip(input.chunks(4)) {
73 | *v = W(LittleEndian::read_u32(c));
74 | }
75 |
76 | // round 1
77 | process!(a, b, c, d, data[0] + CONSTS[0][0], 7, f);
78 | process!(d, a, b, c, data[1] + CONSTS[0][1], 12, f);
79 | process!(c, d, a, b, data[2] + CONSTS[0][2], 17, f);
80 | process!(b, c, d, a, data[3] + CONSTS[0][3], 22, f);
81 |
82 | process!(a, b, c, d, data[4] + CONSTS[0][4], 7, f);
83 | process!(d, a, b, c, data[5] + CONSTS[0][5], 12, f);
84 | process!(c, d, a, b, data[6] + CONSTS[0][6], 17, f);
85 | process!(b, c, d, a, data[7] + CONSTS[0][7], 22, f);
86 |
87 | process!(a, b, c, d, data[8] + CONSTS[0][8], 7, f);
88 | process!(d, a, b, c, data[9] + CONSTS[0][9], 12, f);
89 | process!(c, d, a, b, data[10] + CONSTS[0][10], 17, f);
90 | process!(b, c, d, a, data[11] + CONSTS[0][11], 22, f);
91 |
92 | process!(a, b, c, d, data[12] + CONSTS[0][12], 7, f);
93 | process!(d, a, b, c, data[13] + CONSTS[0][13], 12, f);
94 | process!(c, d, a, b, data[14] + CONSTS[0][14], 17, f);
95 | process!(b, c, d, a, data[15] + CONSTS[0][15], 22, f);
96 |
97 | // round 2
98 | process!(a, b, c, d, data[1] + CONSTS[1][0], 5, g);
99 | process!(d, a, b, c, data[6] + CONSTS[1][1], 9, g);
100 | process!(c, d, a, b, data[11] + CONSTS[1][2], 14, g);
101 | process!(b, c, d, a, data[0] + CONSTS[1][3], 20, g);
102 |
103 | process!(a, b, c, d, data[5] + CONSTS[1][4], 5, g);
104 | process!(d, a, b, c, data[10] + CONSTS[1][5], 9, g);
105 | process!(c, d, a, b, data[15] + CONSTS[1][6], 14, g);
106 | process!(b, c, d, a, data[4] + CONSTS[1][7], 20, g);
107 |
108 | process!(a, b, c, d, data[9] + CONSTS[1][8], 5, g);
109 | process!(d, a, b, c, data[14] + CONSTS[1][9], 9, g);
110 | process!(c, d, a, b, data[3] + CONSTS[1][10], 14, g);
111 | process!(b, c, d, a, data[8] + CONSTS[1][11], 20, g);
112 |
113 | process!(a, b, c, d, data[13] + CONSTS[1][12], 5, g);
114 | process!(d, a, b, c, data[2] + CONSTS[1][13], 9, g);
115 | process!(c, d, a, b, data[7] + CONSTS[1][14], 14, g);
116 | process!(b, c, d, a, data[12] + CONSTS[1][15], 20, g);
117 |
118 | // round 3
119 | process!(a, b, c, d, data[5] + CONSTS[2][0], 4, h);
120 | process!(d, a, b, c, data[8] + CONSTS[2][1], 11, h);
121 | process!(c, d, a, b, data[11] + CONSTS[2][2], 16, h);
122 | process!(b, c, d, a, data[14] + CONSTS[2][3], 23, h);
123 |
124 | process!(a, b, c, d, data[1] + CONSTS[2][4], 4, h);
125 | process!(d, a, b, c, data[4] + CONSTS[2][5], 11, h);
126 | process!(c, d, a, b, data[7] + CONSTS[2][6], 16, h);
127 | process!(b, c, d, a, data[10] + CONSTS[2][7], 23, h);
128 |
129 | process!(a, b, c, d, data[13] + CONSTS[2][8], 4, h);
130 | process!(d, a, b, c, data[0] + CONSTS[2][9], 11, h);
131 | process!(c, d, a, b, data[3] + CONSTS[2][10], 16, h);
132 | process!(b, c, d, a, data[6] + CONSTS[2][11], 23, h);
133 |
134 | process!(a, b, c, d, data[9] + CONSTS[2][12], 4, h);
135 | process!(d, a, b, c, data[12] + CONSTS[2][13], 11, h);
136 | process!(c, d, a, b, data[15] + CONSTS[2][14], 16, h);
137 | process!(b, c, d, a, data[2] + CONSTS[2][15], 23, h);
138 |
139 | // round 4
140 | process!(a, b, c, d, data[0] + CONSTS[3][0], 6, i);
141 | process!(d, a, b, c, data[7] + CONSTS[3][1], 10, i);
142 | process!(c, d, a, b, data[14] + CONSTS[3][2], 15, i);
143 | process!(b, c, d, a, data[5] + CONSTS[3][3], 21, i);
144 |
145 | process!(a, b, c, d, data[12] + CONSTS[3][4], 6, i);
146 | process!(d, a, b, c, data[3] + CONSTS[3][5], 10, i);
147 | process!(c, d, a, b, data[10] + CONSTS[3][6], 15, i);
148 | process!(b, c, d, a, data[1] + CONSTS[3][7], 21, i);
149 |
150 | process!(a, b, c, d, data[8] + CONSTS[3][8], 6, i);
151 | process!(d, a, b, c, data[15] + CONSTS[3][9], 10, i);
152 | process!(c, d, a, b, data[6] + CONSTS[3][10], 15, i);
153 | process!(b, c, d, a, data[13] + CONSTS[3][11], 21, i);
154 |
155 | process!(a, b, c, d, data[4] + CONSTS[3][12], 6, i);
156 | process!(d, a, b, c, data[11] + CONSTS[3][13], 10, i);
157 | process!(c, d, a, b, data[2] + CONSTS[3][14], 15, i);
158 | process!(b, c, d, a, data[9] + CONSTS[3][15], 21, i);
159 |
160 | self.a += a;
161 | self.b += b;
162 | self.c += c;
163 | self.d += d;
164 | }
165 | }
166 |
167 | static CONSTS: [[w32; 16]; 4] = [[W(0xd76aa478),
168 | W(0xe8c7b756),
169 | W(0x242070db),
170 | W(0xc1bdceee),
171 | W(0xf57c0faf),
172 | W(0x4787c62a),
173 | W(0xa8304613),
174 | W(0xfd469501),
175 | W(0x698098d8),
176 | W(0x8b44f7af),
177 | W(0xffff5bb1),
178 | W(0x895cd7be),
179 | W(0x6b901122),
180 | W(0xfd987193),
181 | W(0xa679438e),
182 | W(0x49b40821)],
183 | [W(0xf61e2562),
184 | W(0xc040b340),
185 | W(0x265e5a51),
186 | W(0xe9b6c7aa),
187 | W(0xd62f105d),
188 | W(0x02441453),
189 | W(0xd8a1e681),
190 | W(0xe7d3fbc8),
191 | W(0x21e1cde6),
192 | W(0xc33707d6),
193 | W(0xf4d50d87),
194 | W(0x455a14ed),
195 | W(0xa9e3e905),
196 | W(0xfcefa3f8),
197 | W(0x676f02d9),
198 | W(0x8d2a4c8a)],
199 | [W(0xfffa3942),
200 | W(0x8771f681),
201 | W(0x6d9d6122),
202 | W(0xfde5380c),
203 | W(0xa4beea44),
204 | W(0x4bdecfa9),
205 | W(0xf6bb4b60),
206 | W(0xbebfbc70),
207 | W(0x289b7ec6),
208 | W(0xeaa127fa),
209 | W(0xd4ef3085),
210 | W(0x04881d05),
211 | W(0xd9d4d039),
212 | W(0xe6db99e5),
213 | W(0x1fa27cf8),
214 | W(0xc4ac5665)],
215 | [W(0xf4292244),
216 | W(0x432aff97),
217 | W(0xab9423a7),
218 | W(0xfc93a039),
219 | W(0x655b59c3),
220 | W(0x8f0ccc92),
221 | W(0xffeff47d),
222 | W(0x85845dd1),
223 | W(0x6fa87e4f),
224 | W(0xfe2ce6e0),
225 | W(0xa3014314),
226 | W(0x4e0811a1),
227 | W(0xf7537e82),
228 | W(0xbd3af235),
229 | W(0x2ad7d2bb),
230 | W(0xeb86d391)]];
231 |
232 | /// MD5 implementation
233 | ///
234 | /// For more details check [module docs](index.html)
235 | #[derive(Clone)]
236 | pub struct Md5 {
237 | state: State,
238 | length: u64,
239 | buffer: FixedBuffer64,
240 | }
241 |
242 | impl Default for Md5 {
243 | fn default() -> Self {
244 | Md5 {
245 | state: State::new(),
246 | length: 0,
247 | buffer: FixedBuffer64::new(),
248 | }
249 | }
250 | }
251 |
252 | impl Digest for Md5 {
253 | type OutputBits = U128;
254 | type OutputBytes = U16;
255 |
256 | type BlockSize = U64;
257 |
258 | fn update(&mut self, input: T)
259 | where T: AsRef<[u8]>
260 | {
261 | let input = input.as_ref();
262 | self.length += input.len() as u64;
263 |
264 | let state = &mut self.state;
265 | self.buffer.input(&input[..], |d| state.compress(d));
266 | }
267 |
268 | fn result>(mut self, mut out: T) {
269 | let state = &mut self.state;
270 |
271 | self.buffer.standard_padding(8, |d| state.compress(d));
272 | LittleEndian::write_u64(self.buffer.next(8), self.length << 3);
273 | state.compress(self.buffer.full_buffer());
274 |
275 | let mut out = out.as_mut();
276 | assert!(out.len() >= Self::output_bytes());
277 | LittleEndian::write_u32(&mut out[0..4], state.a.0);
278 | LittleEndian::write_u32(&mut out[4..8], state.b.0);
279 | LittleEndian::write_u32(&mut out[8..12], state.c.0);
280 | LittleEndian::write_u32(&mut out[12..16], state.d.0);
281 | }
282 | }
283 |
--------------------------------------------------------------------------------
/digest/src/ripemd.rs:
--------------------------------------------------------------------------------
1 | //! RIPEMD (RACE Integrity Primitives Evaluation Message Digest)
2 | //!
3 | //! # General info
4 | //!
5 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
6 | //! | ---------- | ----------: | ---------: | -----: | -------------------- | --------------------- |
7 | //! | RIPEMD-160 | 160 bits | 512 bits | 4 | [Merkle–Damgård][md] | [RIPEMD website][web] |
8 | //!
9 | //! [web]: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html "The RIPEMD-160 page"
10 | //! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction
11 |
12 | use byteorder::{ByteOrder, LittleEndian};
13 | use typenum::consts::{U20, U64, U160};
14 | use static_buffer::{FixedBuf, FixedBuffer64, StandardPadding};
15 |
16 | use Digest;
17 |
18 | #[derive(Copy, Clone, Debug)]
19 | struct State {
20 | state: [u32; 5],
21 | }
22 |
23 | macro_rules! process {
24 | () => {};
25 | (proc $block:ident, $value:expr, $rot:expr, $c:expr, $func:block) => {{
26 | let tmp = $block[0]
27 | .wrapping_add($func)
28 | .wrapping_add($value)
29 | .wrapping_add($c)
30 | .rotate_left($rot)
31 | .wrapping_add($block[4]);
32 | $block[0] = $block[4];
33 | $block[4] = $block[3];
34 | $block[3] = $block[2].rotate_left(10);
35 | $block[2] = $block[1];
36 | $block[1] = tmp;
37 | }};
38 | (ff $block:ident, $value:expr, $rot:expr, $c:expr; $($rest:tt)*) => {
39 | process!(proc $block, $value, $rot, $c, { $block[1] ^ $block[2] ^ $block[3] });
40 | process!($($rest)*);
41 | };
42 | (gg $block:ident, $value:expr, $rot:expr, $c:expr; $($rest:tt)*) => {
43 | process!(proc $block, $value, $rot, $c, { ($block[1] & $block[2]) | (!$block[1] & $block[3]) });
44 | process!($($rest)*);
45 | };
46 | (hh $block:ident, $value:expr, $rot:expr, $c:expr; $($rest:tt)*) => {
47 | process!(proc $block, $value, $rot, $c, { ($block[1] | !$block[2]) ^ $block[3] });
48 | process!($($rest)*);
49 | };
50 | (ii $block:ident, $value:expr, $rot:expr, $c:expr; $($rest:tt)*) => {
51 | process!(proc $block, $value, $rot, $c, { ($block[1] & $block[3]) | ($block[2] & !$block[3]) });
52 | process!($($rest)*);
53 | };
54 | (jj $block:ident, $value:expr, $rot:expr, $c:expr; $($rest:tt)*) => {
55 | process!(proc $block, $value, $rot, $c, { $block[1] ^ ($block[2] | !$block[3]) });
56 | process!($($rest)*);
57 | };
58 | ($block:ident;
59 | $round:ident($c:expr, $($v:expr => $r:expr),*)) => {
60 | process! {
61 | $($round $block, $v, $r, $c;)*
62 | }
63 | };
64 | }
65 |
66 | impl State {
67 | fn new() -> Self {
68 | State { state: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0] }
69 | }
70 |
71 | fn process_block(&mut self, block: &[u8]) {
72 | debug_assert!(block.len() == 64);
73 |
74 | let mut data = [0u32; 16];
75 |
76 | for (c, v) in block.chunks(4).zip(data.iter_mut()) {
77 | *v = LittleEndian::read_u32(c);
78 | }
79 |
80 | let mut left = self.state;
81 | let mut right = self.state;
82 |
83 | process!(left; ff(0x00000000,
84 | data[0 ] => 11, data[1 ] => 14, data[2 ] => 15, data[3 ] => 12,
85 | data[4 ] => 5 , data[5 ] => 8 , data[6 ] => 7 , data[7 ] => 9 ,
86 | data[8 ] => 11, data[9 ] => 13, data[10] => 14, data[11] => 15,
87 | data[12] => 6 , data[13] => 7 , data[14] => 9 , data[15] => 8));
88 | process!(left; gg(0x5a827999,
89 | data[7 ] => 7 , data[4 ] => 6 , data[13] => 8 , data[1 ] => 13,
90 | data[10] => 11, data[6 ] => 9 , data[15] => 7 , data[3 ] => 15,
91 | data[12] => 7 , data[0 ] => 12, data[9 ] => 15, data[5 ] => 9 ,
92 | data[2 ] => 11, data[14] => 7 , data[11] => 13, data[8 ] => 12));
93 | process!(left; hh(0x6ed9eba1,
94 | data[3 ] => 11, data[10] => 13, data[14] => 6 , data[4 ] => 7 ,
95 | data[9 ] => 14, data[15] => 9 , data[8 ] => 13, data[1 ] => 15,
96 | data[2 ] => 14, data[7 ] => 8 , data[0 ] => 13, data[6 ] => 6 ,
97 | data[13] => 5 , data[11] => 12, data[5 ] => 7 , data[12] => 5));
98 | process!(left; ii(0x8f1bbcdc,
99 | data[1 ] => 11, data[9 ] => 12, data[11] => 14, data[10] => 15,
100 | data[0 ] => 14, data[8 ] => 15, data[12] => 9 , data[4 ] => 8,
101 | data[13] => 9 , data[3 ] => 14, data[7 ] => 5 , data[15] => 6,
102 | data[14] => 8 , data[5 ] => 6 , data[6 ] => 5 , data[2 ] => 12));
103 | process!(left; jj(0xa953fd4e,
104 | data[4 ] => 9 , data[0 ] => 15, data[5 ] => 5 , data[9 ] => 11,
105 | data[7 ] => 6 , data[12] => 8 , data[2 ] => 13, data[10] => 12,
106 | data[14] => 5 , data[1 ] => 12, data[3 ] => 13, data[8 ] => 14,
107 | data[11] => 11, data[6 ] => 8 , data[15] => 5 , data[13] => 6));
108 |
109 | process!(right; jj(0x50a28be6,
110 | data[5 ] => 8, data[14] => 9 , data[7 ] => 9 , data[0 ] => 11,
111 | data[9 ] => 13, data[2 ] => 15, data[11] => 15, data[4 ] => 5 ,
112 | data[13] => 7 , data[6 ] => 7 , data[15] => 8, data[8 ] => 11,
113 | data[1 ] => 14, data[10] => 14, data[3 ] => 12, data[12] => 6));
114 | process!(right; ii(0x5c4dd124,
115 | data[6 ] => 9 , data[11] => 13, data[3 ] => 15, data[7 ] => 7,
116 | data[0 ] => 12, data[13] => 8 , data[5 ] => 9 , data[10] => 11,
117 | data[14] => 7 , data[15] => 7 , data[8 ] => 12, data[12] => 7 ,
118 | data[4 ] => 6 , data[9 ] => 15, data[1 ] => 13, data[2 ] => 11));
119 | process!(right; hh(0x6d703ef3,
120 | data[15] => 9 , data[5 ] => 7 , data[1 ] => 15, data[3 ] => 11,
121 | data[7 ] => 8 , data[14] => 6 , data[6 ] => 6 , data[9 ] => 14,
122 | data[11] => 12, data[8 ] => 13, data[12] => 5 , data[2 ] => 14,
123 | data[10] => 13, data[0 ] => 13, data[4 ] => 7 , data[13] => 5));
124 | process!(right; gg(0x7a6d76e9,
125 | data[8 ] => 15, data[6 ] => 5 , data[4 ] => 8 , data[1 ] => 11,
126 | data[3 ] => 14, data[11] => 14, data[15] => 6 , data[0 ] => 14,
127 | data[5 ] => 6 , data[12] => 9 , data[2 ] => 12, data[13] => 9 ,
128 | data[9 ] => 12, data[7 ] => 5 , data[10] => 15, data[14] => 8));
129 | process!(right; ff(0x00000000,
130 | data[12] => 8 , data[15] => 5 , data[10] => 12, data[4 ] => 9 ,
131 | data[1 ] => 12, data[5 ] => 5 , data[8 ] => 14, data[7 ] => 6 ,
132 | data[6 ] => 8 , data[2 ] => 13, data[13] => 6 , data[14] => 5 ,
133 | data[0 ] => 15, data[3 ] => 13, data[9 ] => 11, data[11] => 11));
134 |
135 | let tmp = self.state[1].wrapping_add(left[2]).wrapping_add(right[3]);
136 | self.state[1] = self.state[2].wrapping_add(left[3]).wrapping_add(right[4]);
137 | self.state[2] = self.state[3].wrapping_add(left[4]).wrapping_add(right[0]);
138 | self.state[3] = self.state[4].wrapping_add(left[0]).wrapping_add(right[1]);
139 | self.state[4] = self.state[0].wrapping_add(left[1]).wrapping_add(right[2]);
140 | self.state[0] = tmp;
141 | }
142 | }
143 |
144 | /// RIPEMD-160 implementation
145 | ///
146 | /// For more details check [module docs](index.html)
147 | #[derive(Clone)]
148 | pub struct Ripemd160 {
149 | state: State,
150 | length: u64,
151 | buffer: FixedBuffer64,
152 | }
153 |
154 | impl Default for Ripemd160 {
155 | fn default() -> Self {
156 | Ripemd160 {
157 | state: State::new(),
158 | length: 0,
159 | buffer: FixedBuffer64::new(),
160 | }
161 | }
162 | }
163 |
164 | impl Digest for Ripemd160 {
165 | type OutputBits = U160;
166 | type OutputBytes = U20;
167 |
168 | type BlockSize = U64;
169 |
170 | fn update(&mut self, update: T)
171 | where T: AsRef<[u8]>
172 | {
173 | let update = update.as_ref();
174 | self.length += update.len() as u64;
175 |
176 | let state = &mut self.state;
177 | self.buffer.input(update, |d| state.process_block(d));
178 | }
179 |
180 | fn result>(mut self, mut out: T) {
181 | let state = &mut self.state;
182 |
183 | self.buffer.standard_padding(8, |d| state.process_block(d));
184 | LittleEndian::write_u64(self.buffer.next(8), self.length << 3);
185 | state.process_block(self.buffer.full_buffer());
186 |
187 | let mut out = out.as_mut();
188 | assert!(out.len() >= Self::output_bytes());
189 | for (c, &v) in out.chunks_mut(4).zip(&state.state) {
190 | LittleEndian::write_u32(c, v);
191 | }
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/digest/src/sha1/intrinsics.rs:
--------------------------------------------------------------------------------
1 | use simd::u32x4;
2 |
3 | const K0: u32 = 0x5A827999u32;
4 | const K1: u32 = 0x6ED9EBA1u32;
5 | const K2: u32 = 0x8F1BBCDCu32;
6 | const K3: u32 = 0xCA62C1D6u32;
7 |
8 | #[inline]
9 | pub fn first_add(val: u32, u32x4(a, b, c, d): u32x4) -> u32x4 {
10 | u32x4(a.wrapping_add(val), b, c, d)
11 | }
12 |
13 | /// Emulates `llvm.x86.sha1nexte` intrinsic.
14 | #[inline]
15 | pub fn first_half(abcd: u32x4, msg: u32x4) -> u32x4 {
16 | first_add(abcd.0.rotate_left(30), msg)
17 | }
18 |
19 | /// Emulates `llvm.x86.sha1msg1` intrinsic.
20 | #[inline]
21 | fn sha1msg1(a: u32x4, b: u32x4) -> u32x4 {
22 | let u32x4(_, _, w2, w3) = a;
23 | let u32x4(w4, w5, _, _) = b;
24 | a ^ u32x4(w2, w3, w4, w5)
25 | }
26 |
27 | /// Emulates `llvm.x86.sha1msg2` intrinsic.
28 | #[inline]
29 | fn sha1msg2(a: u32x4, b: u32x4) -> u32x4 {
30 | let u32x4(x0, x1, x2, x3) = a;
31 | let u32x4(_, w13, w14, w15) = b;
32 |
33 | let w16 = (x0 ^ w13).rotate_left(1);
34 | let w17 = (x1 ^ w14).rotate_left(1);
35 | let w18 = (x2 ^ w15).rotate_left(1);
36 | let w19 = (x3 ^ w16).rotate_left(1);
37 |
38 | u32x4(w16, w17, w18, w19)
39 | }
40 |
41 | /// Performs 4 rounds of the message schedule update.
42 | #[inline]
43 | pub fn schedule(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4 {
44 | sha1msg2(sha1msg1(v0, v1) ^ v2, v3)
45 | }
46 |
47 | #[inline]
48 | pub fn round_x4(h0: u32x4, h1: u32x4, wk: u32x4, i: i8) -> u32x4 {
49 | digest_round_x4(h0, first_half(h1, wk), i)
50 | }
51 |
52 | /// Emulates `llvm.x86.sha1rnds4` intrinsic.
53 | /// Performs 4 rounds of the message block digest.
54 | #[inline]
55 | pub fn digest_round_x4(abcd: u32x4, work: u32x4, i: i8) -> u32x4 {
56 | const K0V: u32x4 = u32x4(K0, K0, K0, K0);
57 | const K1V: u32x4 = u32x4(K1, K1, K1, K1);
58 | const K2V: u32x4 = u32x4(K2, K2, K2, K2);
59 | const K3V: u32x4 = u32x4(K3, K3, K3, K3);
60 |
61 | match i {
62 | 0 => sha1rnds4c(abcd, work + K0V),
63 | 1 => sha1rnds4p(abcd, work + K1V),
64 | 2 => sha1rnds4m(abcd, work + K2V),
65 | 3 => sha1rnds4p(abcd, work + K3V),
66 | _ => unreachable!("unknown icosaround index"),
67 | }
68 | }
69 |
70 | /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
71 | fn sha1rnds4c(abcd: u32x4, msg: u32x4) -> u32x4 {
72 | let u32x4(mut a, mut b, mut c, mut d) = abcd;
73 | let u32x4(t, u, v, w) = msg;
74 | let mut e = 0u32;
75 |
76 | macro_rules! bool3ary_202 {
77 | ($a:expr, $b:expr, $c:expr) => (($c ^ ($a & ($b ^ $c))))
78 | } // Choose, MD5F, SHA1C
79 |
80 | e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_202!(b, c, d)).wrapping_add(t);
81 | b = b.rotate_left(30);
82 |
83 | d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_202!(a, b, c)).wrapping_add(u);
84 | a = a.rotate_left(30);
85 |
86 | c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_202!(e, a, b)).wrapping_add(v);
87 | e = e.rotate_left(30);
88 |
89 | b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_202!(d, e, a)).wrapping_add(w);
90 | d = d.rotate_left(30);
91 |
92 | u32x4(b, c, d, e)
93 | }
94 |
95 | /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
96 | fn sha1rnds4p(abcd: u32x4, msg: u32x4) -> u32x4 {
97 | let u32x4(mut a, mut b, mut c, mut d) = abcd;
98 | let u32x4(t, u, v, w) = msg;
99 | let mut e = 0u32;
100 |
101 | macro_rules! bool3ary_150 {
102 | ($a:expr, $b:expr, $c:expr) => (($a ^ $b ^ $c))
103 | } // Parity, XOR, MD5H, SHA1P
104 |
105 | e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_150!(b, c, d)).wrapping_add(t);
106 | b = b.rotate_left(30);
107 |
108 | d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_150!(a, b, c)).wrapping_add(u);
109 | a = a.rotate_left(30);
110 |
111 | c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_150!(e, a, b)).wrapping_add(v);
112 | e = e.rotate_left(30);
113 |
114 | b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_150!(d, e, a)).wrapping_add(w);
115 | d = d.rotate_left(30);
116 |
117 | u32x4(b, c, d, e)
118 | }
119 |
120 | /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
121 | fn sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4 {
122 | let u32x4(mut a, mut b, mut c, mut d) = abcd;
123 | let u32x4(t, u, v, w) = msg;
124 | let mut e = 0u32;
125 |
126 | macro_rules! bool3ary_232 {
127 | ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
128 | } // Majority, SHA1M
129 |
130 | e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_232!(b, c, d)).wrapping_add(t);
131 | b = b.rotate_left(30);
132 |
133 | d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_232!(a, b, c)).wrapping_add(u);
134 | a = a.rotate_left(30);
135 |
136 | c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_232!(e, a, b)).wrapping_add(v);
137 | e = e.rotate_left(30);
138 |
139 | b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_232!(d, e, a)).wrapping_add(w);
140 | d = d.rotate_left(30);
141 |
142 | u32x4(b, c, d, e)
143 | }
144 |
--------------------------------------------------------------------------------
/digest/src/sha1/mod.rs:
--------------------------------------------------------------------------------
1 | //! SHA-1 (Secure Hash Algorithm)
2 | //!
3 | //! # WARNING!!!
4 | //!
5 | //! This hash function has been severely compromised. **Do not use!**
6 | //!
7 | //! Instead you should use SHA-2 or SHA-3 family.
8 | //!
9 | //! # General info
10 | //!
11 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
12 | //! | ----- | ----------: | ---------: | -----: | -------------------- | ----------------------- |
13 | //! | SHA-1 | 160 bits | 512 bits | 80 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
14 | //!
15 | //! [fips180-4]: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf "FIPS 180-4 Secure Hash Standard (SHS)"
16 | //! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction
17 |
18 | use byteorder::{ByteOrder, BigEndian};
19 | use typenum::consts::{U20, U64, U160};
20 | use static_buffer::{FixedBuf, FixedBuffer64, StandardPadding};
21 |
22 | use Digest;
23 | use simd::u32x4;
24 |
25 | mod intrinsics;
26 |
27 | #[derive(Copy, Clone, Debug)]
28 | struct State {
29 | a: u32,
30 | b: u32,
31 | c: u32,
32 | d: u32,
33 | e: u32,
34 | }
35 |
36 | impl State {
37 | fn new() -> Self {
38 | State {
39 | a: 0x67452301,
40 | b: 0xefcdab89,
41 | c: 0x98badcfe,
42 | d: 0x10325476,
43 | e: 0xc3d2e1f0,
44 | }
45 | }
46 |
47 | #[inline]
48 | fn process_block(&mut self, data: &[u8]) {
49 | debug_assert!(data.len() == 64);
50 |
51 | let mut words = [0u32; 16];
52 |
53 | for (word, chunk) in words.iter_mut().zip(data.chunks(4)) {
54 | *word = BigEndian::read_u32(chunk);
55 | }
56 |
57 | // Rounds 0..20
58 | let mut h0 = u32x4(self.a, self.b, self.c, self.d);
59 | let mut w0 = u32x4(words[0], words[1], words[2], words[3]);
60 | let mut h1 = intrinsics::digest_round_x4(h0, intrinsics::first_add(self.e, w0), 0);
61 | let mut w1 = u32x4(words[4], words[5], words[6], words[7]);
62 | h0 = intrinsics::round_x4(h1, h0, w1, 0);
63 | let mut w2 = u32x4(words[8], words[9], words[10], words[11]);
64 | h1 = intrinsics::round_x4(h0, h1, w2, 0);
65 | let mut w3 = u32x4(words[12], words[13], words[14], words[15]);
66 | h0 = intrinsics::round_x4(h1, h0, w3, 0);
67 | let mut w4 = intrinsics::schedule(w0, w1, w2, w3);
68 | h1 = intrinsics::round_x4(h0, h1, w4, 0);
69 |
70 | // Rounds 20..40
71 | w0 = intrinsics::schedule(w1, w2, w3, w4);
72 | h0 = intrinsics::round_x4(h1, h0, w0, 1);
73 | w1 = intrinsics::schedule(w2, w3, w4, w0);
74 | h1 = intrinsics::round_x4(h0, h1, w1, 1);
75 | w2 = intrinsics::schedule(w3, w4, w0, w1);
76 | h0 = intrinsics::round_x4(h1, h0, w2, 1);
77 | w3 = intrinsics::schedule(w4, w0, w1, w2);
78 | h1 = intrinsics::round_x4(h0, h1, w3, 1);
79 | w4 = intrinsics::schedule(w0, w1, w2, w3);
80 | h0 = intrinsics::round_x4(h1, h0, w4, 1);
81 |
82 | // Rounds 40..60
83 | w0 = intrinsics::schedule(w1, w2, w3, w4);
84 | h1 = intrinsics::round_x4(h0, h1, w0, 2);
85 | w1 = intrinsics::schedule(w2, w3, w4, w0);
86 | h0 = intrinsics::round_x4(h1, h0, w1, 2);
87 | w2 = intrinsics::schedule(w3, w4, w0, w1);
88 | h1 = intrinsics::round_x4(h0, h1, w2, 2);
89 | w3 = intrinsics::schedule(w4, w0, w1, w2);
90 | h0 = intrinsics::round_x4(h1, h0, w3, 2);
91 | w4 = intrinsics::schedule(w0, w1, w2, w3);
92 | h1 = intrinsics::round_x4(h0, h1, w4, 2);
93 |
94 | // Rounds 60..80
95 | w0 = intrinsics::schedule(w1, w2, w3, w4);
96 | h0 = intrinsics::round_x4(h1, h0, w0, 3);
97 | w1 = intrinsics::schedule(w2, w3, w4, w0);
98 | h1 = intrinsics::round_x4(h0, h1, w1, 3);
99 | w2 = intrinsics::schedule(w3, w4, w0, w1);
100 | h0 = intrinsics::round_x4(h1, h0, w2, 3);
101 | w3 = intrinsics::schedule(w4, w0, w1, w2);
102 | h1 = intrinsics::round_x4(h0, h1, w3, 3);
103 | w4 = intrinsics::schedule(w0, w1, w2, w3);
104 | h0 = intrinsics::round_x4(h1, h0, w4, 3);
105 |
106 | let e = h1.0.rotate_left(30);
107 | let u32x4(a, b, c, d) = h0;
108 |
109 | self.a = self.a.wrapping_add(a);
110 | self.b = self.b.wrapping_add(b);
111 | self.c = self.c.wrapping_add(c);
112 | self.d = self.d.wrapping_add(d);
113 | self.e = self.e.wrapping_add(e);
114 | }
115 | }
116 |
117 | /// SHA-1 implementation
118 | ///
119 | /// For more details check [module docs](index.html)
120 | #[derive(Clone)]
121 | pub struct Sha1 {
122 | state: State,
123 | buffer: FixedBuffer64,
124 | length: u64,
125 | }
126 |
127 | impl Default for Sha1 {
128 | fn default() -> Self {
129 | Sha1 {
130 | state: State::new(),
131 | buffer: FixedBuffer64::new(),
132 | length: 0,
133 | }
134 | }
135 | }
136 |
137 | impl Digest for Sha1 {
138 | type OutputBits = U160;
139 | type OutputBytes = U20;
140 |
141 | type BlockSize = U64;
142 |
143 | fn update>(&mut self, data: T) {
144 | let data = data.as_ref();
145 | self.length += data.len() as u64;
146 |
147 | let state = &mut self.state;
148 | self.buffer.input(data, |d| state.process_block(d));
149 | }
150 |
151 | fn result>(mut self, mut out: T) {
152 | let state = &mut self.state;
153 |
154 | self.buffer.standard_padding(8, |d| state.process_block(d));
155 | BigEndian::write_u64(self.buffer.next(8), self.length * 8);
156 | state.process_block(self.buffer.full_buffer());
157 |
158 | let mut out = out.as_mut();
159 | assert!(out.len() >= Self::output_bytes());
160 | BigEndian::write_u32(&mut out[0..4], state.a);
161 | BigEndian::write_u32(&mut out[4..8], state.b);
162 | BigEndian::write_u32(&mut out[8..12], state.c);
163 | BigEndian::write_u32(&mut out[12..16], state.d);
164 | BigEndian::write_u32(&mut out[16..20], state.e);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/digest/src/sha3.rs:
--------------------------------------------------------------------------------
1 | //! SHA-3 family (Secure Hash Algorithm)
2 | //!
3 | //! # General info
4 | //!
5 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
6 | //! | -------- | ----------: | ---------: | -----: | ---------------- | ------------------- |
7 | //! | SHA3-224 | 224 bits | 1152 bits | 24 | [Sponge][sponge] | [FIPS 202][fips202] |
8 | //! | SHA3-256 | 256 bits | 1088 bits | 24 | [Sponge][sponge] | [FIPS 202][fips202] |
9 | //! | SHA3-384 | 384 bits | 832 bits | 24 | [Sponge][sponge] | [FIPS 202][fips202] |
10 | //! | SHA3-512 | 512 bits | 576 bits | 24 | [Sponge][sponge] | [FIPS 202][fips202] |
11 | //!
12 | //! [fips202]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf "SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions"
13 | //! [sponge]: https://en.wikipedia.org/wiki/Sponge_function "Sponge function"
14 |
15 | use core::ops::Div;
16 | use core::ptr;
17 |
18 | use byteorder::{ByteOrder, LittleEndian};
19 | use typenum::consts::{U8, U72, U104, U136, U144, U224, U256, U384, U512};
20 | use typenum::uint::Unsigned;
21 | use static_buffer::{FixedBuf, FixedBuffer, StandardPadding};
22 |
23 | use Digest;
24 |
25 | #[derive(Copy)]
26 | struct State {
27 | hash: [u64; 25],
28 | rest: usize,
29 | block_size: usize,
30 | }
31 |
32 | impl Clone for State {
33 | fn clone(&self) -> Self {
34 | State {
35 | hash: self.hash,
36 | rest: self.rest,
37 | block_size: self.block_size,
38 | }
39 | }
40 | }
41 |
42 | const ROUND_CONSTS: [u64; 24] = [0x0000000000000001,
43 | 0x0000000000008082,
44 | 0x800000000000808a,
45 | 0x8000000080008000,
46 | 0x000000000000808b,
47 | 0x0000000080000001,
48 | 0x8000000080008081,
49 | 0x8000000000008009,
50 | 0x000000000000008a,
51 | 0x0000000000000088,
52 | 0x0000000080008009,
53 | 0x000000008000000a,
54 | 0x000000008000808b,
55 | 0x800000000000008b,
56 | 0x8000000000008089,
57 | 0x8000000000008003,
58 | 0x8000000000008002,
59 | 0x8000000000000080,
60 | 0x000000000000800a,
61 | 0x800000008000000a,
62 | 0x8000000080008081,
63 | 0x8000000000008080,
64 | 0x0000000080000001,
65 | 0x8000000080008008];
66 |
67 | impl State {
68 | fn init(bits: usize) -> Self {
69 | let rate = 1600 - bits * 2;
70 | assert!(rate <= 1600 && (rate % 64) == 0);
71 | State {
72 | hash: [0; 25],
73 | rest: 0,
74 | block_size: rate / 8,
75 | }
76 | }
77 |
78 | fn permutation(&mut self) {
79 | let mut a: [u64; 25] = self.hash;
80 | let mut c: [u64; 5] = [a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20],
81 | a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21],
82 | a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22],
83 | a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23],
84 | a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]];
85 | for i in 0..12 {
86 | self.round(i * 2, &mut a, &mut c);
87 | self.round(i * 2 + 1, &mut a, &mut c);
88 | }
89 | self.hash = a;
90 | }
91 |
92 | #[inline(always)]
93 | fn round(&self, i: usize, a: &mut [u64; 25], c: &mut [u64; 5]) {
94 | let d0 = c[4] ^ c[1].rotate_left(1);
95 | let d1 = c[0] ^ c[2].rotate_left(1);
96 | let d2 = c[1] ^ c[3].rotate_left(1);
97 | let d3 = c[2] ^ c[4].rotate_left(1);
98 | let d4 = c[3] ^ c[0].rotate_left(1);
99 |
100 | let b0 = a[0] ^ d0;
101 | let b10 = (a[1] ^ d1).rotate_left(1);
102 | let b20 = (a[2] ^ d2).rotate_left(62);
103 | let b5 = (a[3] ^ d3).rotate_left(28);
104 | let b15 = (a[4] ^ d4).rotate_left(27);
105 | let b16 = (a[5] ^ d0).rotate_left(36);
106 | let b1 = (a[6] ^ d1).rotate_left(44);
107 | let b11 = (a[7] ^ d2).rotate_left(6);
108 | let b21 = (a[8] ^ d3).rotate_left(55);
109 | let b6 = (a[9] ^ d4).rotate_left(20);
110 | let b7 = (a[10] ^ d0).rotate_left(3);
111 | let b17 = (a[11] ^ d1).rotate_left(10);
112 | let b2 = (a[12] ^ d2).rotate_left(43);
113 | let b12 = (a[13] ^ d3).rotate_left(25);
114 | let b22 = (a[14] ^ d4).rotate_left(39);
115 | let b23 = (a[15] ^ d0).rotate_left(41);
116 | let b8 = (a[16] ^ d1).rotate_left(45);
117 | let b18 = (a[17] ^ d2).rotate_left(15);
118 | let b3 = (a[18] ^ d3).rotate_left(21);
119 | let b13 = (a[19] ^ d4).rotate_left(8);
120 | let b14 = (a[20] ^ d0).rotate_left(18);
121 | let b24 = (a[21] ^ d1).rotate_left(2);
122 | let b9 = (a[22] ^ d2).rotate_left(61);
123 | let b19 = (a[23] ^ d3).rotate_left(56);
124 | let b4 = (a[24] ^ d4).rotate_left(14);
125 |
126 | a[0] = (b0 ^ ((!b1) & b2)) ^ ROUND_CONSTS[i];
127 | c[0] = a[0];
128 | a[1] = b1 ^ ((!b2) & b3);
129 | c[1] = a[1];
130 | a[2] = b2 ^ ((!b3) & b4);
131 | c[2] = a[2];
132 | a[3] = b3 ^ ((!b4) & b0);
133 | c[3] = a[3];
134 | a[4] = b4 ^ ((!b0) & b1);
135 | c[4] = a[4];
136 |
137 | a[5] = b5 ^ ((!b6) & b7);
138 | c[0] ^= a[5];
139 | a[6] = b6 ^ ((!b7) & b8);
140 | c[1] ^= a[6];
141 | a[7] = b7 ^ ((!b8) & b9);
142 | c[2] ^= a[7];
143 | a[8] = b8 ^ ((!b9) & b5);
144 | c[3] ^= a[8];
145 | a[9] = b9 ^ ((!b5) & b6);
146 | c[4] ^= a[9];
147 |
148 | a[10] = b10 ^ ((!b11) & b12);
149 | c[0] ^= a[10];
150 | a[11] = b11 ^ ((!b12) & b13);
151 | c[1] ^= a[11];
152 | a[12] = b12 ^ ((!b13) & b14);
153 | c[2] ^= a[12];
154 | a[13] = b13 ^ ((!b14) & b10);
155 | c[3] ^= a[13];
156 | a[14] = b14 ^ ((!b10) & b11);
157 | c[4] ^= a[14];
158 |
159 | a[15] = b15 ^ ((!b16) & b17);
160 | c[0] ^= a[15];
161 | a[16] = b16 ^ ((!b17) & b18);
162 | c[1] ^= a[16];
163 | a[17] = b17 ^ ((!b18) & b19);
164 | c[2] ^= a[17];
165 | a[18] = b18 ^ ((!b19) & b15);
166 | c[3] ^= a[18];
167 | a[19] = b19 ^ ((!b15) & b16);
168 | c[4] ^= a[19];
169 |
170 | a[20] = b20 ^ ((!b21) & b22);
171 | c[0] ^= a[20];
172 | a[21] = b21 ^ ((!b22) & b23);
173 | c[1] ^= a[21];
174 | a[22] = b22 ^ ((!b23) & b24);
175 | c[2] ^= a[22];
176 | a[23] = b23 ^ ((!b24) & b20);
177 | c[3] ^= a[23];
178 | a[24] = b24 ^ ((!b20) & b21);
179 | c[4] ^= a[24];
180 | }
181 |
182 | fn process(&mut self, data: &[u8]) {
183 | let max = self.block_size / 8;
184 | for (h, c) in self.hash[0..max].iter_mut().zip(data.chunks(8)) {
185 | *h ^= LittleEndian::read_u64(c)
186 | }
187 |
188 | self.permutation();
189 | }
190 | }
191 |
192 | macro_rules! sha3_impl {
193 | ($(#[$attr:meta])* struct $name:ident -> $size:ty, $bsize:ty) => {
194 | #[derive(Clone)]
195 | $(#[$attr])*
196 | pub struct $name {
197 | state: State,
198 | buffer: FixedBuffer<$bsize>,
199 | }
200 |
201 | impl Default for $name {
202 | fn default() -> Self {
203 | $name {
204 | state: State::init(<$size as Unsigned>::to_usize()),
205 | buffer: FixedBuffer::new(),
206 | }
207 | }
208 | }
209 |
210 | impl Digest for $name {
211 | type OutputBits = $size;
212 | type OutputBytes = <$size as Div>::Output;
213 |
214 | type BlockSize = $bsize;
215 |
216 | fn update(&mut self, data: T) where T: AsRef<[u8]> {
217 | let state = &mut self.state;
218 | self.buffer.input(data.as_ref(), |d| state.process(d));
219 | }
220 |
221 | fn result(mut self, mut out: T) where T: AsMut<[u8]> {
222 | let mut ret = out.as_mut();
223 | assert!(ret.len() >= Self::output_bytes());
224 | let state = &mut self.state;
225 |
226 | self.buffer.pad(0b00000110, 0, |d| state.process(d));
227 | let buf = self.buffer.full_buffer();
228 | let last = buf.len() - 1;
229 | buf[last] |= 0b10000000;
230 | state.process(buf);
231 |
232 | unsafe {
233 | ptr::copy_nonoverlapping(
234 | state.hash.as_ptr() as *const u8,
235 | ret.as_mut_ptr(),
236 | Self::output_bytes())
237 | };
238 | }
239 | }
240 | }
241 | }
242 |
243 | sha3_impl!(
244 | /// SHA3-224 implementation
245 | ///
246 | /// For more details check [module docs](index.html)
247 | struct Sha224 -> U224, U144);
248 | sha3_impl!(
249 | /// SHA3-256 implementation
250 | ///
251 | /// For more details check [module docs](index.html)
252 | struct Sha256 -> U256, U136);
253 | sha3_impl!(
254 | /// SHA3-384 implementation
255 | ///
256 | /// For more details check [module docs](index.html)
257 | struct Sha384 -> U384, U104);
258 | sha3_impl!(
259 | /// SHA3-512 implementation
260 | ///
261 | /// For more details check [module docs](index.html)
262 | struct Sha512 -> U512, U72);
263 |
--------------------------------------------------------------------------------
/digest/src/simd.rs:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 or the MIT license
3 | // , at your
4 | // option. This file may not be copied, modified, or distributed
5 | // except according to those terms.
6 | //
7 | // Based on: https://github.com/DaGenix/rust-crypto/blob/e8a513310f5d8e7bf445723bd0231002f144490c/src/simd.rs
8 |
9 | pub use self::fake::*;
10 |
11 | pub trait SimdExt {
12 | fn simd_eq(self, rhs: Self) -> Self;
13 | }
14 |
15 | impl SimdExt for fake::u32x4 {
16 | fn simd_eq(self, rhs: Self) -> Self {
17 | if self == rhs {
18 | fake::u32x4(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
19 | } else {
20 | fake::u32x4(0, 0, 0, 0)
21 | }
22 | }
23 | }
24 |
25 | mod fake {
26 | use core::ops::{Add, BitAnd, BitOr, BitXor, Shl, Shr, Sub};
27 |
28 | #[derive(Clone, Copy, PartialEq, Eq)]
29 | #[allow(non_camel_case_types)]
30 | pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
31 |
32 | impl Add for u32x4 {
33 | type Output = u32x4;
34 |
35 | fn add(self, rhs: u32x4) -> u32x4 {
36 | u32x4(self.0.wrapping_add(rhs.0),
37 | self.1.wrapping_add(rhs.1),
38 | self.2.wrapping_add(rhs.2),
39 | self.3.wrapping_add(rhs.3))
40 | }
41 | }
42 |
43 | impl Sub for u32x4 {
44 | type Output = u32x4;
45 |
46 | fn sub(self, rhs: u32x4) -> u32x4 {
47 | u32x4(self.0.wrapping_sub(rhs.0),
48 | self.1.wrapping_sub(rhs.1),
49 | self.2.wrapping_sub(rhs.2),
50 | self.3.wrapping_sub(rhs.3))
51 | }
52 | }
53 |
54 | impl BitAnd for u32x4 {
55 | type Output = u32x4;
56 |
57 | fn bitand(self, rhs: u32x4) -> u32x4 {
58 | u32x4(self.0 & rhs.0,
59 | self.1 & rhs.1,
60 | self.2 & rhs.2,
61 | self.3 & rhs.3)
62 | }
63 | }
64 |
65 | impl BitOr for u32x4 {
66 | type Output = u32x4;
67 |
68 | fn bitor(self, rhs: u32x4) -> u32x4 {
69 | u32x4(self.0 | rhs.0,
70 | self.1 | rhs.1,
71 | self.2 | rhs.2,
72 | self.3 | rhs.3)
73 | }
74 | }
75 |
76 | impl BitXor for u32x4 {
77 | type Output = u32x4;
78 |
79 | fn bitxor(self, rhs: u32x4) -> u32x4 {
80 | u32x4(self.0 ^ rhs.0,
81 | self.1 ^ rhs.1,
82 | self.2 ^ rhs.2,
83 | self.3 ^ rhs.3)
84 | }
85 | }
86 |
87 | impl Shl for u32x4 {
88 | type Output = u32x4;
89 |
90 | fn shl(self, amt: usize) -> u32x4 {
91 | u32x4(self.0 << amt, self.1 << amt, self.2 << amt, self.3 << amt)
92 | }
93 | }
94 |
95 | impl Shl for u32x4 {
96 | type Output = u32x4;
97 |
98 | fn shl(self, rhs: u32x4) -> u32x4 {
99 | u32x4(self.0 << rhs.0,
100 | self.1 << rhs.1,
101 | self.2 << rhs.2,
102 | self.3 << rhs.3)
103 | }
104 | }
105 |
106 | impl Shr for u32x4 {
107 | type Output = u32x4;
108 |
109 | fn shr(self, amt: usize) -> u32x4 {
110 | u32x4(self.0 >> amt, self.1 >> amt, self.2 >> amt, self.3 >> amt)
111 | }
112 | }
113 |
114 | impl Shr for u32x4 {
115 | type Output = u32x4;
116 |
117 | fn shr(self, rhs: u32x4) -> u32x4 {
118 | u32x4(self.0 >> rhs.0,
119 | self.1 >> rhs.1,
120 | self.2 >> rhs.2,
121 | self.3 >> rhs.3)
122 | }
123 | }
124 |
125 | #[derive(Clone, Copy)]
126 | #[allow(non_camel_case_types)]
127 | pub struct u64x2(pub u64, pub u64);
128 |
129 | impl Add for u64x2 {
130 | type Output = u64x2;
131 |
132 | fn add(self, rhs: u64x2) -> u64x2 {
133 | u64x2(self.0.wrapping_add(rhs.0), self.1.wrapping_add(rhs.1))
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/digest/src/tiger/mod.rs:
--------------------------------------------------------------------------------
1 | //! Tiger
2 | //!
3 | //! # General info
4 | //!
5 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
6 | //! | ----------- | ----------: | ---------: | -----: | -------------------- | -------------------- |
7 | //! | Tiger | 192 bits | 512 bits | 24 | [Merkle–Damgård][md] | [Tiger website][web] |
8 | //! | Tiger2 | 192 bits | 512 bits | 24 | [Merkle–Damgård][md] | [Tiger website][web] |
9 | //!
10 | //! [web]: http://www.cs.technion.ac.il/~biham/Reports/Tiger/ "Tiger: A Fast New Hash Function(Designed in 1995)"
11 | //! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction
12 |
13 | use static_buffer::{FixedBuffer64, FixedBuf, StandardPadding};
14 | use byteorder::{ByteOrder, BigEndian};
15 | use typenum::consts::{U24, U64, U192};
16 |
17 | use wrapping::*;
18 |
19 | use Digest;
20 |
21 | use self::sboxes::SBOXES;
22 |
23 | mod sboxes;
24 |
25 | const ROUNDS: usize = 3;
26 |
27 | #[derive(Debug, Clone, Copy)]
28 | struct State {
29 | a: w64,
30 | b: w64,
31 | c: w64,
32 | }
33 |
34 | macro_rules! round {
35 | ($a:expr, $b:expr, $c:expr, $x:expr, $mul:expr) => {
36 | $c = $c ^ $x;
37 | $a = $a - W(
38 | SBOXES[0][($c.0 >> 0) as u8 as usize] ^
39 | SBOXES[1][($c.0 >> 16) as u8 as usize] ^
40 | SBOXES[2][($c.0 >> 32) as u8 as usize] ^
41 | SBOXES[3][($c.0 >> 48) as u8 as usize]);
42 | $b = $b + W(
43 | SBOXES[3][($c.0 >> 8) as u8 as usize] ^
44 | SBOXES[2][($c.0 >> 24) as u8 as usize] ^
45 | SBOXES[1][($c.0 >> 40) as u8 as usize] ^
46 | SBOXES[0][($c.0 >> 56) as u8 as usize]);
47 | $b = $b * W($mul);
48 | };
49 | }
50 |
51 | #[inline]
52 | fn key_schedule(x: &mut [w64]) {
53 | x[0] = x[0] - (x[7] ^ W(0xa5a5a5a5a5a5a5a5));
54 | x[1] = x[1] ^ x[0];
55 | x[2] = x[2] + x[1];
56 | x[3] = x[3] - (x[2] ^ (!x[1] << 19));
57 | x[4] = x[4] ^ x[3];
58 | x[5] = x[5] + x[4];
59 | x[6] = x[6] - (x[5] ^ (!x[4] >> 23));
60 | x[7] = x[7] ^ x[6];
61 |
62 | x[0] = x[0] + x[7];
63 | x[1] = x[1] - (x[0] ^ (!x[7] << 19));
64 | x[2] = x[2] ^ x[1];
65 | x[3] = x[3] + x[2];
66 | x[4] = x[4] - (x[3] ^ (!x[2] >> 23));
67 | x[5] = x[5] ^ x[4];
68 | x[6] = x[6] + x[5];
69 | x[7] = x[7] - (x[6] ^ W(0x0123456789abcdef));
70 | }
71 |
72 | impl State {
73 | fn new() -> Self {
74 | State {
75 | a: W(0x0123456789abcdef),
76 | b: W(0xfedcba9876543210),
77 | c: W(0xf096a5b4c3b2e187),
78 | }
79 | }
80 |
81 | #[inline]
82 | fn pass(&mut self, block: &[W], mul: u64) {
83 | round!(self.a, self.b, self.c, block[0], mul);
84 | round!(self.b, self.c, self.a, block[1], mul);
85 | round!(self.c, self.a, self.b, block[2], mul);
86 | round!(self.a, self.b, self.c, block[3], mul);
87 | round!(self.b, self.c, self.a, block[4], mul);
88 | round!(self.c, self.a, self.b, block[5], mul);
89 | round!(self.a, self.b, self.c, block[6], mul);
90 | round!(self.b, self.c, self.a, block[7], mul);
91 | }
92 |
93 | #[inline]
94 | fn rotate(&mut self) {
95 | let tmp = self.a;
96 | self.a = self.c;
97 | self.c = self.b;
98 | self.b = tmp;
99 | }
100 |
101 | #[inline]
102 | fn compress(&mut self, block: &[u8]) {
103 | debug_assert!(block.len() == 64);
104 | let mut wblock = [W(0); 8];
105 |
106 | for (v, c) in wblock.iter_mut().zip(block.chunks(8)) {
107 | *v = W(BigEndian::read_u64(c));
108 | }
109 |
110 | let tmp = *self; // save abc
111 |
112 | for i in 0..ROUNDS {
113 | if i != 0 {
114 | key_schedule(&mut wblock);
115 | }
116 | let mul = match i {
117 | 0 => 5,
118 | 1 => 7,
119 | _ => 9,
120 | };
121 | self.pass(&wblock, mul);
122 | self.rotate();
123 | }
124 |
125 | // feedforward
126 | self.a ^= tmp.a;
127 | self.b -= tmp.b;
128 | self.c += tmp.c;
129 | }
130 | }
131 |
132 | macro_rules! tiger_impl {
133 | ($(#[$meta:meta])* struct $name:ident, $padding:expr) => {
134 | $(#[$meta])*
135 | #[derive(Clone)]
136 | pub struct $name {
137 | state: State,
138 | buffer: FixedBuffer64,
139 | length: u64,
140 | }
141 |
142 | impl Default for $name {
143 | fn default() -> Self {
144 | $name {
145 | state: State::new(),
146 | buffer: FixedBuffer64::new(),
147 | length: 0,
148 | }
149 | }
150 | }
151 |
152 | impl Digest for $name {
153 | type OutputBits = U192;
154 | type OutputBytes = U24;
155 |
156 | type BlockSize = U64;
157 |
158 | fn update(&mut self, update: T)
159 | where T: AsRef<[u8]>
160 | {
161 | let update = update.as_ref();
162 | self.length += update.len() as u64;
163 |
164 | let state = &mut self.state;
165 | self.buffer.input(update, |d| state.compress(d));
166 | }
167 |
168 | fn result(mut self, mut out: T)
169 | where T: AsMut<[u8]>
170 | {
171 | let state = &mut self.state;
172 |
173 | self.buffer.pad($padding, 8, |d| state.compress(d));
174 | BigEndian::write_u64(self.buffer.next(8), self.length << 3);
175 | state.compress(self.buffer.full_buffer());
176 |
177 | let mut out = out.as_mut();
178 | assert!(out.len() >= Self::output_bytes());
179 | BigEndian::write_u64(&mut out[0..8], state.a.0);
180 | BigEndian::write_u64(&mut out[8..16], state.b.0);
181 | BigEndian::write_u64(&mut out[16..24], state.c.0);
182 | }
183 | }
184 | };
185 | }
186 |
187 | tiger_impl!(
188 | /// Tiger implementation
189 | ///
190 | /// For more details check [module docs](index.html)
191 | struct Tiger, 0x01);
192 | tiger_impl!(
193 | /// Tiger2 implementation
194 | ///
195 | /// The only difference between original Tiger and Tiger2 is padding value which is `0b00000001`
196 | /// (`0x01`) for Tiger and `0b10000000` (`0x80`, the same that is used by MD-4/5 and SHA-1/2)
197 | /// for Tiger2.
198 | ///
199 | /// For more details check [module docs](index.html)
200 | struct Tiger2, 0x80);
201 |
--------------------------------------------------------------------------------
/digest/src/whirlpool/mod.rs:
--------------------------------------------------------------------------------
1 | //! WHIRLPOOL
2 | //!
3 | //! # General info
4 | //!
5 | //! | Name | Digest size | Block size | Rounds | Structure | Reference |
6 | //! | ----------- | ----------: | ---------: | -----: | ---------------------------------------------------------------------- | ------------------------ |
7 | //! | WHIRLPOOL | 192 bits | 512 bits | 10 | [Miyaguchi-Preneel][mp] hashing with [Merkle–Damgård][md] strengthning | [WHIRLPOOL website][web] |
8 | //!
9 | //! [web]: http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html "The WHIRLPOOL Hash Function"
10 | //! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction
11 | //! [mp]: https://en.wikipedia.org/wiki/One-way_compression_function#Miyaguchi.E2.80.93Preneel
12 |
13 | #![allow(eq_op)]
14 |
15 | use static_buffer::{FixedBuffer64, FixedBuf, StandardPadding};
16 | use byteorder::{ByteOrder, BigEndian};
17 | use typenum::consts::{U64, U512};
18 |
19 | use Digest;
20 | use wrapping::*;
21 |
22 | use self::sboxes::SBOXES;
23 |
24 | mod sboxes;
25 |
26 | const ROUNDS: usize = 10;
27 |
28 | const RC: [w64; ROUNDS] = [W(0x1823c6e887b8014f),
29 | W(0x36a6d2f5796f9152),
30 | W(0x60bc9b8ea30c7b35),
31 | W(0x1de0d7c22e4bfe57),
32 | W(0x157737e59ff04ada),
33 | W(0x58c9290ab1a06b85),
34 | W(0xbd5d10f4cb3e0567),
35 | W(0xe427418ba77d95d8),
36 | W(0xfbee7c66dd17479e),
37 | W(0xca2dbf07ad5a8333)];
38 |
39 | #[inline(always)]
40 | fn op(src: [w64; 8], shift: usize) -> w64 {
41 | W(SBOXES[0][(src[(shift) % 8] >> 56).0 as u8 as usize] ^
42 | SBOXES[1][(src[(shift + 7) % 8] >> 48).0 as u8 as usize] ^
43 | SBOXES[2][(src[(shift + 6) % 8] >> 40).0 as u8 as usize] ^
44 | SBOXES[3][(src[(shift + 5) % 8] >> 32).0 as u8 as usize] ^
45 | SBOXES[4][(src[(shift + 4) % 8] >> 24).0 as u8 as usize] ^
46 | SBOXES[5][(src[(shift + 3) % 8] >> 16).0 as u8 as usize] ^
47 | SBOXES[6][(src[(shift + 2) % 8] >> 8).0 as u8 as usize] ^
48 | SBOXES[7][(src[(shift + 1) % 8]).0 as u8 as usize])
49 | }
50 |
51 | #[inline]
52 | fn key_schedule(key: [w64; 8], rc: w64) -> [w64; 8] {
53 | [
54 | op(key, 0) ^ rc,
55 | op(key, 1),
56 | op(key, 2),
57 | op(key, 3),
58 | op(key, 4),
59 | op(key, 5),
60 | op(key, 6),
61 | op(key, 7),
62 | ]
63 | }
64 |
65 | #[inline]
66 | fn message_schedule(state: [w64; 8], key: [w64; 8]) -> [w64; 8] {
67 | [
68 | op(state, 0) ^ key[0],
69 | op(state, 1) ^ key[1],
70 | op(state, 2) ^ key[2],
71 | op(state, 3) ^ key[3],
72 | op(state, 4) ^ key[4],
73 | op(state, 5) ^ key[5],
74 | op(state, 6) ^ key[6],
75 | op(state, 7) ^ key[7],
76 | ]
77 | }
78 |
79 | #[derive(Debug, Clone, Copy)]
80 | struct State {
81 | hash: [w64; 8],
82 | }
83 |
84 | impl State {
85 | fn new() -> Self {
86 | State { hash: [W(0); 8] }
87 | }
88 |
89 | #[inline(always)]
90 | fn compress(&mut self, data: &[u8]) {
91 | debug_assert!(data.len() == 64);
92 | let mut key = self.hash;
93 | let mut state = [W(0u64); 8];
94 |
95 | for ((word, chunk), state) in self.hash
96 | .iter_mut()
97 | .zip(data.chunks(8))
98 | .zip(&mut state) {
99 | *state = W(BigEndian::read_u64(chunk)) ^ *word;
100 | *word = *state;
101 | }
102 |
103 | for &rc in &RC {
104 | key = key_schedule(key, rc);
105 | state = message_schedule(state, key);
106 | }
107 |
108 | for (hash, &state) in self.hash.iter_mut().zip(&state) {
109 | *hash ^= state
110 | }
111 | }
112 | }
113 |
114 | /// WHIRLPOOL implementation
115 | ///
116 | /// For details check out [module documentation](index.html)
117 | #[derive(Clone)]
118 | pub struct Whirlpool {
119 | state: State,
120 | buffer: FixedBuffer64,
121 | length: u64,
122 | }
123 |
124 | impl Default for Whirlpool {
125 | fn default() -> Self {
126 | Whirlpool {
127 | state: State::new(),
128 | buffer: FixedBuffer64::new(),
129 | length: 0,
130 | }
131 | }
132 | }
133 |
134 | impl Digest for Whirlpool {
135 | type OutputBits = U512;
136 | type OutputBytes = U64;
137 |
138 | type BlockSize = U64;
139 |
140 | fn update(&mut self, update: T)
141 | where T: AsRef<[u8]>
142 | {
143 | let update = update.as_ref();
144 | self.length += update.len() as u64;
145 |
146 | let state = &mut self.state;
147 | self.buffer.input(update, |d| state.compress(d));
148 | }
149 |
150 | fn result(mut self, mut out: T)
151 | where T: AsMut<[u8]>
152 | {
153 | let mut out = out.as_mut();
154 | assert!(out.len() >= Self::output_bytes());
155 | {
156 | let state = &mut self.state;
157 |
158 | self.buffer.standard_padding(32, |d| state.compress(d));
159 | self.buffer.zero_until(56);
160 | BigEndian::write_u64(self.buffer.next(8), self.length * 8);
161 | state.compress(self.buffer.full_buffer());
162 | }
163 |
164 | for (&word, chunk) in self.state.hash.iter().zip(out.chunks_mut(8)) {
165 | BigEndian::write_u64(chunk, word.0);
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/digest/src/wrapping.rs:
--------------------------------------------------------------------------------
1 | pub use core::num::Wrapping as W;
2 |
3 | #[allow(non_camel_case_types)]
4 | pub type w32 = W;
5 | #[allow(non_camel_case_types)]
6 | pub type w64 = W;
7 |
8 | pub trait Rotate {
9 | fn rotate_right(self, rotation: u32) -> Self;
10 | fn rotate_left(self, rotation: u32) -> Self;
11 | }
12 |
13 | macro_rules! impl_rotate {
14 | ($typ:path) => {
15 | impl Rotate for $typ {
16 | #[inline]
17 | fn rotate_right(self, rotation: u32) -> Self {
18 | $typ(self.0.rotate_right(rotation))
19 | }
20 |
21 | #[inline]
22 | fn rotate_left(self, rotation: u32) -> Self {
23 | $typ(self.0.rotate_left(rotation))
24 | }
25 | }
26 | };
27 | }
28 |
29 | impl_rotate!(W);
30 | impl_rotate!(W);
31 |
--------------------------------------------------------------------------------
/digest/tests/blake2/mod.rs:
--------------------------------------------------------------------------------
1 | use std::path::Path;
2 | use std::fs::File;
3 | use std::io::Read;
4 |
5 | use toml;
6 |
7 | use utils::tests::Data;
8 |
9 | #[derive(RustcDecodable)]
10 | pub struct Test {
11 | input: Data,
12 | key: Data,
13 | output: Data,
14 | }
15 |
16 | #[derive(RustcDecodable)]
17 | pub struct Suite {
18 | tests: Vec,
19 | }
20 |
21 | pub fn load>(path: P) -> Suite {
22 | let mut content = String::new();
23 | File::open(path).and_then(|mut f| f.read_to_string(&mut content)).unwrap();
24 |
25 | toml::decode_str(&content).unwrap()
26 | }
27 |
28 | mod blake2b {
29 | use super::*;
30 |
31 | use digest::blake2::Blake2b512;
32 | use digest::Digest;
33 |
34 | use std::str;
35 | use rustc_serialize::hex::ToHex;
36 |
37 | #[test]
38 | fn reference_test_vectors() {
39 | let suite = load("./tests/blake2/blake2b.toml");
40 |
41 | for test in suite.tests {
42 | let mut digest = Blake2b512::with_key(&*test.key);
43 | digest.update(&*test.input);
44 |
45 | let mut output = vec![0; 64];
46 | digest.result(&mut output[..]);
47 |
48 | assert!(&*test.output == &output[..],
49 | "Input: {:?} (str: \"{}\")\nKey: {}\nExpected: {}\nGot: {}",
50 | test.input,
51 | str::from_utf8(&*test.input).unwrap_or(""),
52 | test.key.to_hex(),
53 | test.output.to_hex(),
54 | output.to_hex());
55 | }
56 | }
57 | }
58 |
59 | mod blake2s {
60 | use super::*;
61 |
62 | use digest::blake2::Blake2s256;
63 | use digest::Digest;
64 |
65 | use std::str;
66 | use rustc_serialize::hex::ToHex;
67 |
68 | #[test]
69 | fn reference_test_vectors() {
70 | let suite = load("./tests/blake2/blake2s.toml");
71 |
72 | for test in suite.tests {
73 | let mut digest = Blake2s256::with_key(&*test.key);
74 | digest.update(&*test.input);
75 |
76 | let mut output = vec![0; 32];
77 | digest.result(&mut output[..]);
78 |
79 | assert!(&*test.output == &output[..],
80 | "Input: {:?} (str: \"{}\")\nKey: {}\nExpected: {}\nGot: {}",
81 | test.input,
82 | str::from_utf8(&*test.input).unwrap_or(""),
83 | test.key.to_hex(),
84 | test.output.to_hex(),
85 | output.to_hex());
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/digest/tests/lib.rs:
--------------------------------------------------------------------------------
1 | extern crate octavo_digest as digest;
2 | extern crate toml;
3 | extern crate rustc_serialize;
4 |
5 | #[macro_use]
6 | mod utils;
7 |
8 | #[cfg(feature = "blake2")]
9 | mod blake2;
10 | #[cfg(feature = "md5")]
11 | mod md5;
12 | // #[cfg(feature = "ripemd")]
13 | // mod ripemd;
14 | #[cfg(feature = "sha1")]
15 | mod sha1;
16 | #[cfg(feature = "sha2")]
17 | mod sha2;
18 | #[cfg(feature = "sha3")]
19 | mod sha3;
20 | #[cfg(feature = "tiger")]
21 | mod tiger;
22 | #[cfg(feature = "whirlpool")]
23 | mod whirlpool;
24 |
--------------------------------------------------------------------------------
/digest/tests/md5/mod.rs:
--------------------------------------------------------------------------------
1 | use digest::md5::Md5;
2 |
3 | // use TestCase;
4 |
5 | // const TESTS: [TestCase<'static>; 7] =
6 | // [TestCase {
7 | // input: b"",
8 | // output: &[0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec,
9 | // 0xf8, 0x42, 0x7e],
10 | // },
11 | // TestCase {
12 | // input: b"a",
13 | // output: &[0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69,
14 | // 0x77, 0x26, 0x61],
15 | // },
16 | // TestCase {
17 | // input: b"abc",
18 | // output: &[0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28,
19 | // 0xe1, 0x7f, 0x72],
20 | // },
21 | // TestCase {
22 | // input: b"message digest",
23 | // output: &[0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa,
24 | // 0xf1, 0x61, 0xd0],
25 | // },
26 | // TestCase {
27 | // input: b"abcdefghijklmnopqrstuvwxyz",
28 | // output: &[0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca,
29 | // 0x67, 0xe1, 0x3b],
30 | // },
31 | // TestCase {
32 | // input: b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
33 | // output: &[0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f,
34 | // 0x41, 0x9d, 0x9f],
35 | // },
36 | // TestCase {
37 | // input: b"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
38 | // output: &[0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21,
39 | // 0x07, 0xb6, 0x7a],
40 | // }];
41 |
42 | use utils;
43 |
44 | #[test]
45 | fn rfc1321_test_vectors() {
46 | let suite = utils::load("./tests/md5/rfc1321.toml");
47 |
48 | for test in suite.tests {
49 | test.test(Md5::default());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/digest/tests/md5/rfc1321.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:d41d8cd98f00b204e9800998ecf8427e"
4 |
5 | [[tests]]
6 | input = "a"
7 | output = "hex:0cc175b9c0f1b6a831c399e269772661"
8 |
9 | [[tests]]
10 | input = "abc"
11 | output = "hex:900150983cd24fb0d6963f7d28e17f72"
12 |
13 | [[tests]]
14 | input = "message digest"
15 | output = "hex:f96b697d7cb7938d525a2f31aaf161d0"
16 |
17 | [[tests]]
18 | input = "abcdefghijklmnopqrstuvwxyz"
19 | output = "hex:c3fcd3d76192e4007dfb496cca67e13b"
20 |
21 | [[tests]]
22 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
23 | output = "hex:d174ab98d277d9f5a5611c2c9f419d9f"
24 |
25 | [[tests]]
26 | input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
27 | output = "hex:57edf4a22be3c955ac49da2e2107b67a"
28 |
--------------------------------------------------------------------------------
/digest/tests/ripemd/mod.rs:
--------------------------------------------------------------------------------
1 | use digest::ripemd::*;
2 |
3 | use TestCase;
4 |
5 | const TESTS: &'static [TestCase<'static>] =
6 | &[TestCase {
7 | input: b"",
8 | output: &[0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, 0x08, 0x97, 0x7e,
9 | 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31],
10 | },
11 | TestCase {
12 | input: b"a",
13 | output: &[0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, 0x34, 0x7b, 0xe6,
14 | 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe],
15 | },
16 | TestCase {
17 | input: b"abc",
18 | output: &[0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98,
19 | 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc],
20 | },
21 | TestCase {
22 | input: b"message digest",
23 | output: &[0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, 0x81, 0xb1, 0x23,
24 | 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36],
25 | },
26 | TestCase {
27 | input: b"abcdefghijklmnopqrstuvwxyz",
28 | output: &[0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, 0xdc, 0xeb, 0x5b,
29 | 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc],
30 | },
31 | TestCase {
32 | input: b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
33 | output: &[0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, 0xa0, 0x6c, 0x27,
34 | 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b],
35 | },
36 | TestCase {
37 | input: b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
38 | output: &[0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, 0x3a, 0x87, 0xa5,
39 | 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89],
40 | }];
41 |
42 | #[test]
43 | fn simple_test_vectors() {
44 | for test in TESTS {
45 | test.test(Ripemd160::default());
46 | }
47 | }
48 |
49 | digest_quick!(Ripemd160, Type::RIPEMD160);
50 |
--------------------------------------------------------------------------------
/digest/tests/sha1/mod.rs:
--------------------------------------------------------------------------------
1 | use digest::sha1::Sha1;
2 |
3 | use utils;
4 |
5 | #[test]
6 | fn shavs_short() {
7 | let suite = utils::load("./tests/sha1/shavs/short.toml");
8 |
9 | for test in suite.tests {
10 | test.test(Sha1::default())
11 | }
12 | }
13 |
14 | #[test]
15 | fn shavs_long() {
16 | let suite = utils::load("./tests/sha1/shavs/long.toml");
17 |
18 | for test in suite.tests {
19 | test.test(Sha1::default())
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/digest/tests/sha1/shavs/short.toml:
--------------------------------------------------------------------------------
1 | # CAVS 11."0"
2 | # "SHA-1 ShortMsg" information
3 | # SHA-1 tests are configured for BYTE oriented implementations
4 | # Generated on Tue Mar 15 08:23:35 "2011"
5 |
6 | [[tests]]
7 | input = "hex:36"
8 | output = "hex:c1dfd96eea8cc2b62785275bca38ac261256e278"
9 |
10 | [[tests]]
11 | input = "hex:195a"
12 | output = "hex:0a1c2d555bbe431ad6288af5a54f93e0449c9232"
13 |
14 | [[tests]]
15 | input = "hex:df4bd2"
16 | output = "hex:bf36ed5d74727dfd5d7854ec6b1d49468d8ee8aa"
17 |
18 | [[tests]]
19 | input = "hex:549e959e"
20 | output = "hex:b78bae6d14338ffccfd5d5b5674a275f6ef9c717"
21 |
22 | [[tests]]
23 | input = "hex:f7fb1be205"
24 | output = "hex:60b7d5bb560a1acf6fa45721bd0abb419a841a89"
25 |
26 | [[tests]]
27 | input = "hex:c0e5abeaea63"
28 | output = "hex:a6d338459780c08363090fd8fc7d28dc80e8e01f"
29 |
30 | [[tests]]
31 | input = "hex:63bfc1ed7f78ab"
32 | output = "hex:860328d80509500c1783169ebf0ba0c4b94da5e5"
33 |
34 | [[tests]]
35 | input = "hex:7e3d7b3eada98866"
36 | output = "hex:24a2c34b976305277ce58c2f42d5092031572520"
37 |
38 | [[tests]]
39 | input = "hex:9e61e55d9ed37b1c20"
40 | output = "hex:411ccee1f6e3677df12698411eb09d3ff580af97"
41 |
42 | [[tests]]
43 | input = "hex:9777cf90dd7c7e863506"
44 | output = "hex:05c915b5ed4e4c4afffc202961f3174371e90b5c"
45 |
46 | [[tests]]
47 | input = "hex:4eb08c9e683c94bea00dfa"
48 | output = "hex:af320b42d7785ca6c8dd220463be23a2d2cb5afc"
49 |
50 | [[tests]]
51 | input = "hex:0938f2e2ebb64f8af8bbfc91"
52 | output = "hex:9f4e66b6ceea40dcf4b9166c28f1c88474141da9"
53 |
54 | [[tests]]
55 | input = "hex:74c9996d14e87d3e6cbea7029d"
56 | output = "hex:e6c4363c0852951991057f40de27ec0890466f01"
57 |
58 | [[tests]]
59 | input = "hex:51dca5c0f8e5d49596f32d3eb874"
60 | output = "hex:046a7b396c01379a684a894558779b07d8c7da20"
61 |
62 | [[tests]]
63 | input = "hex:3a36ea49684820a2adc7fc4175ba78"
64 | output = "hex:d58a262ee7b6577c07228e71ae9b3e04c8abcda9"
65 |
66 | [[tests]]
67 | input = "hex:3552694cdf663fd94b224747ac406aaf"
68 | output = "hex:a150de927454202d94e656de4c7c0ca691de955d"
69 |
70 | [[tests]]
71 | input = "hex:f216a1cbde2446b1edf41e93481d33e2ed"
72 | output = "hex:35a4b39fef560e7ea61246676e1b7e13d587be30"
73 |
74 | [[tests]]
75 | input = "hex:a3cf714bf112647e727e8cfd46499acd35a6"
76 | output = "hex:7ce69b1acdce52ea7dbd382531fa1a83df13cae7"
77 |
78 | [[tests]]
79 | input = "hex:148de640f3c11591a6f8c5c48632c5fb79d3b7"
80 | output = "hex:b47be2c64124fa9a124a887af9551a74354ca411"
81 |
82 | [[tests]]
83 | input = "hex:63a3cc83fd1ec1b6680e9974a0514e1a9ecebb6a"
84 | output = "hex:8bb8c0d815a9c68a1d2910f39d942603d807fbcc"
85 |
86 | [[tests]]
87 | input = "hex:875a90909a8afc92fb7070047e9d081ec92f3d08b8"
88 | output = "hex:b486f87fb833ebf0328393128646a6f6e660fcb1"
89 |
90 | [[tests]]
91 | input = "hex:444b25f9c9259dc217772cc4478c44b6feff62353673"
92 | output = "hex:76159368f99dece30aadcfb9b7b41dab33688858"
93 |
94 | [[tests]]
95 | input = "hex:487351c8a5f440e4d03386483d5fe7bb669d41adcbfdb7"
96 | output = "hex:dbc1cb575ce6aeb9dc4ebf0f843ba8aeb1451e89"
97 |
98 | [[tests]]
99 | input = "hex:46b061ef132b87f6d3b0ee2462f67d910977da20aed13705"
100 | output = "hex:d7a98289679005eb930ab75efd8f650f991ee952"
101 |
102 | [[tests]]
103 | input = "hex:3842b6137bb9d27f3ca5bafe5bbb62858344fe4ba5c41589a5"
104 | output = "hex:fda26fa9b4874ab701ed0bb64d134f89b9c4cc50"
105 |
106 | [[tests]]
107 | input = "hex:44d91d3d465a4111462ba0c7ec223da6735f4f5200453cf132c3"
108 | output = "hex:c2ff7ccde143c8f0601f6974b1903eb8d5741b6e"
109 |
110 | [[tests]]
111 | input = "hex:cce73f2eabcb52f785d5a6df63c0a105f34a91ca237fe534ee399d"
112 | output = "hex:643c9dc20a929608f6caa9709d843ca6fa7a76f4"
113 |
114 | [[tests]]
115 | input = "hex:664e6e7946839203037a65a12174b244de8cbc6ec3f578967a84f9ce"
116 | output = "hex:509ef787343d5b5a269229b961b96241864a3d74"
117 |
118 | [[tests]]
119 | input = "hex:9597f714b2e45e3399a7f02aec44921bd78be0fefee0c5e9b499488f6e"
120 | output = "hex:b61ce538f1a1e6c90432b233d7af5b6524ebfbe3"
121 |
122 | [[tests]]
123 | input = "hex:75c5ad1f3cbd22e8a95fc3b089526788fb4ebceed3e7d4443da6e081a35e"
124 | output = "hex:5b7b94076b2fc20d6adb82479e6b28d07c902b75"
125 |
126 | [[tests]]
127 | input = "hex:dd245bffe6a638806667768360a95d0574e1a0bd0d18329fdb915ca484ac0d"
128 | output = "hex:6066db99fc358952cf7fb0ec4d89cb0158ed91d7"
129 |
130 | [[tests]]
131 | input = "hex:0321794b739418c24e7c2e565274791c4be749752ad234ed56cb0a6347430c6b"
132 | output = "hex:b89962c94d60f6a332fd60f6f07d4f032a586b76"
133 |
134 | [[tests]]
135 | input = "hex:4c3dcf95c2f0b5258c651fcd1d51bd10425d6203067d0748d37d1340d9ddda7db3"
136 | output = "hex:17bda899c13d35413d2546212bcd8a93ceb0657b"
137 |
138 | [[tests]]
139 | input = "hex:b8d12582d25b45290a6e1bb95da429befcfdbf5b4dd41cdf3311d6988fa17cec0723"
140 | output = "hex:badcdd53fdc144b8bf2cc1e64d10f676eebe66ed"
141 |
142 | [[tests]]
143 | input = "hex:6fda97527a662552be15efaeba32a3aea4ed449abb5c1ed8d9bfff544708a425d69b72"
144 | output = "hex:01b4646180f1f6d2e06bbe22c20e50030322673a"
145 |
146 | [[tests]]
147 | input = "hex:09fa2792acbb2417e8ed269041cc03c77006466e6e7ae002cf3f1af551e8ce0bb506d705"
148 | output = "hex:10016dc3a2719f9034ffcc689426d28292c42fc9"
149 |
150 | [[tests]]
151 | input = "hex:5efa2987da0baf0a54d8d728792bcfa707a15798dc66743754406914d1cfe3709b1374eaeb"
152 | output = "hex:9f42fa2bce6ef021d93c6b2d902273797e426535"
153 |
154 | [[tests]]
155 | input = "hex:2836de99c0f641cd55e89f5af76638947b8227377ef88bfba662e5682babc1ec96c6992bc9a0"
156 | output = "hex:cdf48bacbff6f6152515323f9b43a286e0cb8113"
157 |
158 | [[tests]]
159 | input = "hex:42143a2b9e1d0b354df3264d08f7b602f54aad922a3d63006d097f683dc11b90178423bff2f7fe"
160 | output = "hex:b88fb75274b9b0fd57c0045988cfcef6c3ce6554"
161 |
162 | [[tests]]
163 | input = "hex:eb60c28ad8aeda807d69ebc87552024ad8aca68204f1bcd29dc5a81dd228b591e2efb7c4df75ef03"
164 | output = "hex:c06d3a6a12d9e8db62e8cff40ca23820d61d8aa7"
165 |
166 | [[tests]]
167 | input = "hex:7de4ba85ec54747cdc42b1f23546b7e490e31280f066e52fac117fd3b0792e4de62d5843ee98c72015"
168 | output = "hex:6e40f9e83a4be93874bc97cdebb8da6889ae2c7a"
169 |
170 | [[tests]]
171 | input = "hex:e70653637bc5e388ccd8dc44e5eace36f7398f2bac993042b9bc2f4fb3b0ee7e23a96439dc01134b8c7d"
172 | output = "hex:3efc940c312ef0dfd4e1143812248db89542f6a5"
173 |
174 | [[tests]]
175 | input = "hex:dd37bc9f0b3a4788f9b54966f252174c8ce487cbe59c53c22b81bf77621a7ce7616dcb5b1e2ee63c2c309b"
176 | output = "hex:a0cf03f7badd0c3c3c4ea3717f5a4fb7e67b2e56"
177 |
178 | [[tests]]
179 | input = "hex:5f485c637ae30b1e30497f0fb7ec364e13c906e2813daa34161b7ac4a4fd7a1bddd79601bbd22cef1f57cbc7"
180 | output = "hex:a544e06f1a07ceb175a51d6d9c0111b3e15e9859"
181 |
182 | [[tests]]
183 | input = "hex:f6c237fb3cfe95ec8414cc16d203b4874e644cc9a543465cad2dc563488a659e8a2e7c981e2a9f22e5e868ffe1"
184 | output = "hex:199d986ed991b99a071f450c6b1121a727e8c735"
185 |
186 | [[tests]]
187 | input = "hex:da7ab3291553c659873c95913768953c6e526d3a26590898c0ade89ff56fbd110f1436af590b17fed49f8c4b2b1e"
188 | output = "hex:33bac6104b0ad6128d091b5d5e2999099c9f05de"
189 |
190 | [[tests]]
191 | input = "hex:8cfa5fd56ee239ca47737591cba103e41a18acf8e8d257b0dbe8851134a81ff6b2e97104b39b76e19da256a17ce52d"
192 | output = "hex:76d7db6e18c1f4ae225ce8ccc93c8f9a0dfeb969"
193 |
194 | [[tests]]
195 | input = "hex:57e89659d878f360af6de45a9a5e372ef40c384988e82640a3d5e4b76d2ef181780b9a099ac06ef0f8a7f3f764209720"
196 | output = "hex:f652f3b1549f16710c7402895911e2b86a9b2aee"
197 |
198 | [[tests]]
199 | input = "hex:b91e64235dbd234eea2ae14a92a173ebe835347239cff8b02074416f55c6b60dc6ced06ae9f8d705505f0d617e4b29aef9"
200 | output = "hex:63faebb807f32be708cf00fc35519991dc4e7f68"
201 |
202 | [[tests]]
203 | input = "hex:e42a67362a581e8cf3d847502215755d7ad425ca030c4360b0f7ef513e6980265f61c9fa18dd9ce668f38dbc2a1ef8f83cd6"
204 | output = "hex:0e6730bc4a0e9322ea205f4edfff1fffda26af0a"
205 |
206 | [[tests]]
207 | input = "hex:634db92c22010e1cbf1e1623923180406c515272209a8acc42de05cc2e96a1e94c1f9f6b93234b7f4c55de8b1961a3bf352259"
208 | output = "hex:b61a3a6f42e8e6604b93196c43c9e84d5359e6fe"
209 |
210 | [[tests]]
211 | input = "hex:cc6ca3a8cb391cd8a5aff1faa7b3ffbdd21a5a3ce66cfaddbfe8b179e4c860be5ec66bd2c6de6a39a25622f9f2fcb3fc05af12b5"
212 | output = "hex:32d979ca1b3ed0ed8c890d99ec6dd85e6c16abf4"
213 |
214 | [[tests]]
215 | input = "hex:7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab644466de27bb522fcb99307126ae718fe8f00742e6e5cb7a687c88447cbc961"
216 | output = "hex:6f18190bd2d02fc93bce64756575cea36d08b1c3"
217 |
218 | [[tests]]
219 | input = "hex:c5581d40b331e24003901bd6bf244aca9e9601b9d81252bb38048642731f1146b8a4c69f88e148b2c8f8c14f15e1d6da57b2daa9991e"
220 | output = "hex:68f525feea1d8dbe0117e417ca46708d18d7629a"
221 |
222 | [[tests]]
223 | input = "hex:ec6b4a88713df27c0f2d02e738b69db43abda3921317259c864c1c386e9a5a3f533dc05f3beeb2bec2aac8e06db4c6cb3cddcf697e03d5"
224 | output = "hex:a7272e2308622ff7a339460adc61efd0ea8dabdc"
225 |
226 | [[tests]]
227 | input = "hex:0321736beba578e90abc1a90aa56157d871618f6de0d764cc8c91e06c68ecd3b9de3824064503384db67beb7fe012232dacaef93a000fba7"
228 | output = "hex:aef843b86916c16f66c84d83a6005d23fd005c9e"
229 |
230 | [[tests]]
231 | input = "hex:d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2678ef6d8d521e456bd84aa755328c83fc890837726a8e7877b570dba39579aabdd"
232 | output = "hex:be2cd6f380969be59cde2dff5e848a44e7880bd6"
233 |
234 | [[tests]]
235 | input = "hex:c32138531118f08c7dcc292428ad20b45ab27d9517a18445f38b8f0c2795bcdfe3ffe384e65ecbf74d2c9d0da88398575326074904c1709ba072"
236 | output = "hex:e5eb4543deee8f6a5287845af8b593a95a9749a1"
237 |
238 | [[tests]]
239 | input = "hex:b0f4cfb939ea785eabb7e7ca7c476cdd9b227f015d905368ba00ae96b9aaf720297491b3921267576b72c8f58d577617e844f9f0759b399c6b064c"
240 | output = "hex:534c850448dd486787b62bdec2d4a0b140a1b170"
241 |
242 | [[tests]]
243 | input = "hex:bd02e51b0cf2c2b8d204a026b41a66fbfc2ac37ee9411fc449c8d1194a0792a28ee731407dfc89b6dfc2b10faa27723a184afef8fd83def858a32d3f"
244 | output = "hex:6fbfa6e4edce4cc85a845bf0d228dc39acefc2fa"
245 |
246 | [[tests]]
247 | input = "hex:e33146b83e4bb671392218da9a77f8d9f5974147182fb95ba662cb66011989c16d9af104735d6f79841aa4d1df276615b50108df8a29dbc9de31f4260d"
248 | output = "hex:018872691d9b04e8220e09187df5bc5fa6257cd9"
249 |
250 | [[tests]]
251 | input = "hex:411c13c75073c1e2d4b1ecf13139ba9656cd35c14201f1c7c6f0eeb58d2dbfe35bfdeccc92c3961cfabb590bc1eb77eac15732fb0275798680e0c7292e50"
252 | output = "hex:d98d512a35572f8bd20de62e9510cc21145c5bf4"
253 |
254 | [[tests]]
255 | input = "hex:f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc2165d3074629579079d4d5b86f5081ab177b4c3f530376c9c924cbd421a8daf8830d0940c4fb7589865830699"
256 | output = "hex:9f3ea255f6af95c5454e55d7354cabb45352ea0b"
257 |
258 | [[tests]]
259 | input = "hex:45927e32ddf801caf35e18e7b5078b7f5435278212ec6bb99df884f49b327c6486feae46ba187dc1cc9145121e1492e6b06e9007394dc33b7748f86ac3207cfe"
260 | output = "hex:a70cfbfe7563dd0e665c7c6715a96a8d756950c0"
261 |
--------------------------------------------------------------------------------
/digest/tests/sha2/mod.rs:
--------------------------------------------------------------------------------
1 | mod sha224;
2 | mod sha256;
3 | mod sha384;
4 | mod sha512;
5 |
--------------------------------------------------------------------------------
/digest/tests/sha2/sha224.rs:
--------------------------------------------------------------------------------
1 | use digest::sha2::Sha224;
2 |
3 | use utils;
4 |
5 | #[test]
6 | fn shavs_short() {
7 | let suite = utils::load("./tests/sha2/shavs/sha224/short.toml");
8 |
9 | for test in suite.tests {
10 | test.test(Sha224::default())
11 | }
12 | }
13 |
14 | #[test]
15 | fn shavs_long() {
16 | let suite = utils::load("./tests/sha2/shavs/sha224/long.toml");
17 |
18 | for test in suite.tests {
19 | test.test(Sha224::default())
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/digest/tests/sha2/sha256.rs:
--------------------------------------------------------------------------------
1 | use digest::sha2::Sha256;
2 |
3 | use utils;
4 |
5 | #[test]
6 | fn shavs_short() {
7 | let suite = utils::load("./tests/sha2/shavs/sha256/short.toml");
8 |
9 | for test in suite.tests {
10 | test.test(Sha256::default())
11 | }
12 | }
13 |
14 | #[test]
15 | fn shavs_long() {
16 | let suite = utils::load("./tests/sha2/shavs/sha256/long.toml");
17 |
18 | for test in suite.tests {
19 | test.test(Sha256::default())
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/digest/tests/sha2/sha384.rs:
--------------------------------------------------------------------------------
1 | use digest::sha2::Sha384;
2 |
3 | use utils;
4 |
5 | #[test]
6 | fn shavs_short() {
7 | let suite = utils::load("./tests/sha2/shavs/sha384/short.toml");
8 |
9 | for test in suite.tests {
10 | test.test(Sha384::default())
11 | }
12 | }
13 |
14 | #[test]
15 | fn shavs_long() {
16 | let suite = utils::load("./tests/sha2/shavs/sha384/long.toml");
17 |
18 | for test in suite.tests {
19 | test.test(Sha384::default())
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/digest/tests/sha2/sha512.rs:
--------------------------------------------------------------------------------
1 | use digest::sha2::Sha512;
2 |
3 | use utils;
4 |
5 | #[test]
6 | fn shavs_short() {
7 | let suite = utils::load("./tests/sha2/shavs/sha512/short.toml");
8 |
9 | for test in suite.tests {
10 | test.test(Sha512::default())
11 | }
12 | }
13 |
14 | #[test]
15 | fn shavs_long() {
16 | let suite = utils::load("./tests/sha2/shavs/sha512/long.toml");
17 |
18 | for test in suite.tests {
19 | test.test(Sha512::default())
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/digest/tests/sha2/shavs/sha224/short.toml:
--------------------------------------------------------------------------------
1 | # CAVS 11.0
2 | # "SHA-224 Shortinput" information
3 | # SHA-224 tests are configured for BYTE oriented implementations
4 | # Generated on Tue Mar 15 08:23:36 2011
5 |
6 | [[tests]]
7 | input = "hex:84"
8 | output = "hex:3cd36921df5d6963e73739cf4d20211e2d8877c19cff087ade9d0e3a"
9 |
10 | [[tests]]
11 | input = "hex:5c7b"
12 | output = "hex:daff9bce685eb831f97fc1225b03c275a6c112e2d6e76f5faf7a36e6"
13 |
14 | [[tests]]
15 | input = "hex:51ca3d"
16 | output = "hex:2c8959023515476e38388abb43599a29876b4b33d56adc06032de3a2"
17 |
18 | [[tests]]
19 | input = "hex:6084347e"
20 | output = "hex:ae57c0a6d49739ba338adfa53bdae063e5c09122b77604780a8eeaa3"
21 |
22 | [[tests]]
23 | input = "hex:493e14623c"
24 | output = "hex:7f631f295e024e74552083245ca8f988a3fb65680ae97c3040d2e65c"
25 |
26 | [[tests]]
27 | input = "hex:d729d8cd1631"
28 | output = "hex:342e8e6b23c1c6a54910631f098e08e836259c57e49c1b1d023d166d"
29 |
30 | [[tests]]
31 | input = "hex:cbf2061e10faa5"
32 | output = "hex:3aa702b1b66dc57d7aec3ccdbdfbd88592d7520f843ba5d0fa481168"
33 |
34 | [[tests]]
35 | input = "hex:5f77b3664823c33e"
36 | output = "hex:bdf21ff325f754157ccf417f4855360a72e8fd117d28c8fe7da3ea38"
37 |
38 | [[tests]]
39 | input = "hex:10713b894de4a734c0"
40 | output = "hex:03842600c86f5cd60c3a2147a067cb962a05303c3488b05cb45327bd"
41 |
42 | [[tests]]
43 | input = "hex:006470d57dad9893dc03"
44 | output = "hex:c90026cda5ad24115059c62ae9add57793ade445d4742273288bbce7"
45 |
46 | [[tests]]
47 | input = "hex:6f29ca274190400720bba2"
48 | output = "hex:ac53157947aa4b2a19089182382a4363d182dd8e4ca79cd8571390be"
49 |
50 | [[tests]]
51 | input = "hex:17e8556176fcca2addbdde29"
52 | output = "hex:cc6ad0488db0222066f740557b5758a19b30372b302332295d8c3aff"
53 |
54 | [[tests]]
55 | input = "hex:dbf163601db9a122a4026824de"
56 | output = "hex:9849845f4e47e1ece9a1c1e01a0d896ffea61c6c8894a75a11ce5f49"
57 |
58 | [[tests]]
59 | input = "hex:5e1ef2ad86ceaf5439fe87d2ec9b"
60 | output = "hex:223c5d5d4a0116b32cea044f9af0fe44babea1c5ab201502591bcd5f"
61 |
62 | [[tests]]
63 | input = "hex:65f3b9866fb8002b53cfaf806f702f"
64 | output = "hex:b1e0806a218d593821fde8e9eacc44ab5287c32209a94f011ab66b75"
65 |
66 | [[tests]]
67 | input = "hex:b776708ffb91b3515ac46598ab9fa796"
68 | output = "hex:427311b1d7ab2488791c4deeb4251d783fe5f9806bfdfb5188c5443d"
69 |
70 | [[tests]]
71 | input = "hex:a4bc10b1a62c96d459fbaf3a5aa3face73"
72 | output = "hex:d7e6634723ac25cb1879bdb1508da05313530419013fe255967a39e1"
73 |
74 | [[tests]]
75 | input = "hex:9e8f3c6645c1749b55c50d2018ce40dc2427"
76 | output = "hex:2f5a583bf588c8988a572d128a95bea5ef1b66780a7d4be9c29efc31"
77 |
78 | [[tests]]
79 | input = "hex:2db6d207c0b7d9117f24d78ee59abf2f316978"
80 | output = "hex:35681fce28307cae19522c23cbd4a77969347f7d8ee4a3088ba90ada"
81 |
82 | [[tests]]
83 | input = "hex:3df5e7f399f6dd61a12a9d4e9464fc4997c1f37b"
84 | output = "hex:a3e68076e30751085a843a6cbfbf0f3dee63d9c4219c914372e50b28"
85 |
86 | [[tests]]
87 | input = "hex:65781d018f27ca0c72a9fa9ab4648ed369646dd3ce"
88 | output = "hex:d15ef0d872d02da6427b8d0349dea2f204e67133b7365b4b150efc3c"
89 |
90 | [[tests]]
91 | input = "hex:af48eeddd93fee69d1bd7de428a63986011d10945eaf"
92 | output = "hex:b89d428ee42e397cf11029ecbb27baddd036c8938f51c8ab56b875ac"
93 |
94 | [[tests]]
95 | input = "hex:df2bf0d5f9c994ac69d78baa0d512eceb74d8a047531c1"
96 | output = "hex:db8e1ce68c8c6b84d6db755c2b8bf54f3c4b081a881efcddaf303294"
97 |
98 | [[tests]]
99 | input = "hex:48d2f20955ea2d13433c20bc0404eb2e6ad79ed28f7cb4c0"
100 | output = "hex:3617cc3179f8b59adce181eebeed5e2763f62650949224a67e53694b"
101 |
102 | [[tests]]
103 | input = "hex:218f74a42d3a47ef3b806601fba024b078cbff4e4b85772e0e"
104 | output = "hex:b5f40b95dcc363b97e9d00b67c5d7c37f17ab563297d2d67a4df20c9"
105 |
106 | [[tests]]
107 | input = "hex:ef55b1e797000b04fcdb9b3021b09327e3b4e269d20cabdf418f"
108 | output = "hex:827b223d51240c2e3271c534c19c5637b6fe10083e85bcf06761ef21"
109 |
110 | [[tests]]
111 | input = "hex:96df4387dc2c40297043bea36483f65e4eb1e07e93359cb7e68610"
112 | output = "hex:98e430a63fcdedafc9419010f7f59a4d816a45b4f973beb62530ff8c"
113 |
114 | [[tests]]
115 | input = "hex:3ec0aa8d30d5ed825b77dc7095f421b1e608158797a377ff8bed641b"
116 | output = "hex:3108321eb7ff857f6aae69101b937f32a51ea279a6c14ba5232ac8c1"
117 |
118 | [[tests]]
119 | input = "hex:8b0239712039f077ce323b35f4e306787b9b35270096e57735cff45d84"
120 | output = "hex:a5c740d3ce46bb2e0a048488f2b0605c6d0ca0ea2f382d043d13db97"
121 |
122 | [[tests]]
123 | input = "hex:044be30167a9758c46c727921dc4eb4e0dcb965623423e6fdd44e7a4ea52"
124 | output = "hex:6eb78313c743ea8769d8340f284dda6ded64a1db64392f21abb82c5c"
125 |
126 | [[tests]]
127 | input = "hex:57f6118bacce47ecc31ce8b0c083d3c9219e0dbe9e4fbea154537c41231acc"
128 | output = "hex:0dbb53c866d63af44c222c76c825df0e379dcedfb958db03b6fd29a5"
129 |
130 | [[tests]]
131 | input = "hex:fe1f0fb02c9011f4c8c5905934ed15136771737ce31c5859e67f235fe594f5f6"
132 | output = "hex:bbeaacc632c2a3db2a9b47f157ab54aa27776c6e74cf0bcaa91b06d5"
133 |
134 | [[tests]]
135 | input = "hex:14fb01ae9d6015ecb3e56d6ecdfa4bc0533186adf8457f5e4a5c57c687895f3db3"
136 | output = "hex:178272c7d7cc71b15074c27e3b7997d4a3ba99626986a1a16cf30030"
137 |
138 | [[tests]]
139 | input = "hex:ff6c49712f044f4063c14125c0cdfba18ed8b7138453768a45dfa2d82a05f1e84227"
140 | output = "hex:403284c888a7280bc8bfc25f0c34182cd378306a21a1404d4e1c40cf"
141 |
142 | [[tests]]
143 | input = "hex:f900bd7e0117247f97c8fc7a665c76a35f571c3366571d6c4a3ee5d7fb93f1d1f726e2"
144 | output = "hex:48235b9820d66d8885faabf6a9ede63ba2a21b6177e987a33242373e"
145 |
146 | [[tests]]
147 | input = "hex:42d38188ac49440cfefb77db975e083e6b22348c4c67f0f8692e88ad140d861dc828d595"
148 | output = "hex:615344f890e5bcf71b5efe39de1fc942ba1fe30dd9e9146adb6a41bf"
149 |
150 | [[tests]]
151 | input = "hex:74fdd7d958b8ae7c2c3c5cff4266dfb2b3b842c9f59ecbbcaff575edcbcda08ccd6e08b764"
152 | output = "hex:66d7d6c54fc7775a0ba845ba3e11719fa535b9289f20b098c5f7a342"
153 |
154 | [[tests]]
155 | input = "hex:934416dd0581e22f2bfbece7bb64afe820451fa21342df7e6f9fb37c4103381a1f7cd379bcc4"
156 | output = "hex:fae8f1aa22def4dbaa814c5b0babdec43394951792c937050d2963a6"
157 |
158 | [[tests]]
159 | input = "hex:102401c84a716ae72579c6ae79c359ea309ffd95abffae4c61884c03c9e99df77b6c92e492cacb"
160 | output = "hex:8f34812d57a16ef8a51ad987660c5f8623e0fa9d89846e28d46d14d9"
161 |
162 | [[tests]]
163 | input = "hex:79bc8fb60f85d15a2386566e3e7314df284533085add1c7bb6ead3ff760c86d5633a66404761b544"
164 | output = "hex:65c54014cfa30f0bc27d1c6efa96ae8481f4c2505bff272956eab0df"
165 |
166 | [[tests]]
167 | input = "hex:db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c4f834b7c3f1e7931a4a7f7a9"
168 | output = "hex:9316d2f021c2913d63a7e66924c87c161c3cfde0ea7ba07f54772862"
169 |
170 | [[tests]]
171 | input = "hex:0dd51aa660c5cb4b7f78c46852c1db8707ab451c1367b6187388c8bb3873a1aa4210d0414cc6792a29a7"
172 | output = "hex:31989e7a62a5132a5070d77250d8904bb82d457dc63469d06b50185e"
173 |
174 | [[tests]]
175 | input = "hex:487fd2e5b694b7071d3789a258a51e8604dc0d3e8f5d62f39131968e602abe1ddf6b0278962a512408b553"
176 | output = "hex:e798683438284626d710877d9eea3a0e02f349fc43acb7f9f8f9e81c"
177 |
178 | [[tests]]
179 | input = "hex:11183bdebfef58e4da5b1cb73be0d30b20da304d8659d921da2e270fd14626799537e4d12119e809ee97004a"
180 | output = "hex:96870657d6cb668be3995aa8bd31df77840d1d1915d72482e83b6b2c"
181 |
182 | [[tests]]
183 | input = "hex:a239de5c8e2644e8f030d94d98f1a30664e6fd961dc2977a9c08be5c31d8de89450945a53d79299ea2a1edde7f"
184 | output = "hex:e99743d4fd26c8800c36a67b6762247c29da6b62794123c59de06dc0"
185 |
186 | [[tests]]
187 | input = "hex:917c4577aa6b0f9df49999fc1c958cb09b7fd5fc80be949670f03545eb27dcaed052076b24f96f5e0f2e2f4527c0"
188 | output = "hex:7ecd693d4d9cf43929464698efa0bac33c2e1424f816edc769260978"
189 |
190 | [[tests]]
191 | input = "hex:c3f1e735a6741aa481ad577a98dbac1f03cc80ea0dae1b94db2369ed4e93facd29c64e4e77b25038279120bdfa3715"
192 | output = "hex:86f0d89d8e14fd8b6606412d71a7a54a347b304ea5d49c208f2266ab"
193 |
194 | [[tests]]
195 | input = "hex:de4fbfd553cdf37019f25afa82dc6b9970f4bb1ebbc37f80d3084c88a70722cdc523a9e3c2afbad0dc0221bfdec9a2f9"
196 | output = "hex:4c5262acb4a2a44eaa9bc6757024fb202ef4d5a7a16fa37252a422b5"
197 |
198 | [[tests]]
199 | input = "hex:db2e2eb636610cf42e9b33433acce1b3b925949f297dd83199f45d2861d64cd910c2db74a60b2089045e22cba0a536137d"
200 | output = "hex:16bf4e45bcdc60447c68dcb30e6b08f55ce9f4124a29cf1f9a9d065d"
201 |
202 | [[tests]]
203 | input = "hex:a8e729d336d5d6ac50e1e22f0b193b66e26042fc6459214129875e740ab2b142918c138aaf941863ad3b7e6065450613b273"
204 | output = "hex:452bf2e5ebfc4e451cc434bc09e2a10032eed0b7627cf55e7e5ed0e2"
205 |
206 | [[tests]]
207 | input = "hex:d05317d4b535f9d10f739d0c2dedf3ffb090c1ad9d205089b1346693f58273c4925c0face57ba45ad6fc687c66a88fc78878be"
208 | output = "hex:4f03c439e097b51b00e314f675937c4d911505859fb7ab16adc65e44"
209 |
210 | [[tests]]
211 | input = "hex:26bb4ed4f0424c60fe4212ff8c955e89e2f553a7d7701be59416d2089af59fa1074724e214e919b1e30f33fb78374b4b055bbc9b"
212 | output = "hex:e7c899e27009d4dc77c2d300f191b757e52c9e7eac4b023bfab2b52a"
213 |
214 | [[tests]]
215 | input = "hex:f015ec83944f03292463c4345fdb1c26d1ea07645facbc9520ae244b6eb191e53dabadb4ac0fb15cda4ed77dfb9e1193abfafb1b81"
216 | output = "hex:459e40b3fbd612912f0217c60099379ce077cd02505871b0c9c14e7a"
217 |
218 | [[tests]]
219 | input = "hex:0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c809cb4171bfa4791539aca1abd91900e53ba93ca0efd"
220 | output = "hex:fadebab7c3d0fb8e97e429b79083087735e4ab385a789521260ef3ad"
221 |
222 | [[tests]]
223 | input = "hex:445e8698eeb8accbaac4ffa7d934fffd16014a430ef70f3a9174c6cfe96d1e3f6ab1377f4a7212dbb30146dd17d9f470c4dffc45b8e871"
224 | output = "hex:4c7ae028c0fe61f2a9cada61fae30685b77f04c6442576e912af9fa6"
225 |
226 | [[tests]]
227 | input = "hex:52839f2f0853a30df14ec897a1914c685c1ac21470d00654c8c37663bfb65fa732dbb694d9dd09ced723b48d8f545846ba168988b61cc724"
228 | output = "hex:2f755a57674b49d5c25cb37348f35b6fd2de2552c749f2645ba63d20"
229 |
230 | [[tests]]
231 | input = "hex:5fe8c2072d8900287ccaf07f3f66b0c22acd3e0bb91d9573754e19e373ac35271d8b43443436ac0c162850ef3d7f281409ad29a9bf716c77d1"
232 | output = "hex:42909757f6e229f69f04cc7a863c4e70e48c7c3575057b455c959775"
233 |
234 | [[tests]]
235 | input = "hex:e8064d83f3d643af8718c87e3ccd6a9733685eac61d572a22ab943f232fcb04f70858e8984449db14a76bb7eaf2458efc3ed2a32100622c52b7f"
236 | output = "hex:1a1d8ed54cb45c97bc970754b43eb93d9eabde4c7b07f76ad82d8ede"
237 |
238 | [[tests]]
239 | input = "hex:87c9a517e28d1bb54ad20fca76460efd894d7786e68ee8d746b2f68208682157c8ad06cc324ad7a3189e09c6c39d4c768719c0a49a41669f2767d5"
240 | output = "hex:605977cf87b9b309bbddaaa64e528ace66b04df9f72c0e7ec88be1da"
241 |
242 | [[tests]]
243 | input = "hex:59fdac3b6b32039291801c7d6f46ede8d26dc5b7a192e007116739b617569f2523680b3c0b6631af453e55805aa760c6970833ac06963bbc9dbd455e"
244 | output = "hex:e9f0cb1dc8337e906385892f2348a8ba4412318ecad9b96e3711531f"
245 |
246 | [[tests]]
247 | input = "hex:30350a4df0b58ff49c0fa09e426fcd7007b290c760c825c1855d9b0023b82caa51e3cab4c60cfa61492be50568e5ac0f6db0fd468e39e4536403e3809f"
248 | output = "hex:776cc6636c02408fbf65ace73ae80017108b917c16c5a912fd860241"
249 |
250 | [[tests]]
251 | input = "hex:ef797a0d43c30b4fe1014bdb9420879c2ff845d27e73d55a7df22930c8ece73253d8bb265b4ef2ff9c69455cc56ff25229b4126bb7bb26ee2c9ff36187b1"
252 | output = "hex:f5b9ffb102affac352a4a535a00f89b06c268cf4881d712668906025"
253 |
254 | [[tests]]
255 | input = "hex:716944de41710c29b659be10480bb25a351a39e577ee30e8f422d57cf62ad95bda39b6e70c61426e33fd84aca84cc7912d5eee45dc34076a5d2323a15c7964"
256 | output = "hex:61645ac748db567ac862796b8d06a47afebfa2e1783d5c5f3bcd81e2"
257 |
258 | [[tests]]
259 | input = "hex:a3310ba064be2e14ad32276e18cd0310c933a6e650c3c754d0243c6c61207865b4b65248f66a08edf6e0832689a9dc3a2e5d2095eeea50bd862bac88c8bd318d"
260 | output = "hex:b2a5586d9cbf0baa999157b4af06d88ae08d7c9faab4bc1a96829d65"
261 |
262 |
--------------------------------------------------------------------------------
/digest/tests/sha3/mod.rs:
--------------------------------------------------------------------------------
1 | mod sha224 {
2 | use digest::sha3::Sha224;
3 |
4 | use utils;
5 |
6 | #[test]
7 | fn simple_test_vectors() {
8 | let suite = utils::load("./tests/sha3/sha224.toml");
9 |
10 | for test in suite.tests {
11 | test.test(Sha224::default());
12 | }
13 | }
14 | }
15 |
16 | mod sha256 {
17 | use digest::sha3::Sha256;
18 |
19 | use utils;
20 |
21 | #[test]
22 | fn simple_test_vectors() {
23 | let suite = utils::load("./tests/sha3/sha256.toml");
24 |
25 | for test in suite.tests {
26 | test.test(Sha256::default());
27 | }
28 | }
29 | }
30 |
31 | mod sha384 {
32 | use digest::sha3::Sha384;
33 |
34 | use utils;
35 |
36 | #[test]
37 | fn simple_test_vectors() {
38 | let suite = utils::load("./tests/sha3/sha384.toml");
39 |
40 | for test in suite.tests {
41 | test.test(Sha384::default());
42 | }
43 | }
44 | }
45 |
46 | mod sha512 {
47 | use digest::sha3::Sha512;
48 |
49 | use utils;
50 |
51 | #[test]
52 | fn simple_test_vectors() {
53 | let suite = utils::load("./tests/sha3/sha512.toml");
54 |
55 | for test in suite.tests {
56 | test.test(Sha512::default());
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/digest/tests/sha3/sha224.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"
4 |
5 | [[tests]]
6 | input = "a"
7 | output = "hex:9e86ff69557ca95f405f081269685b38e3a819b309ee942f482b6a8b"
8 |
9 | [[tests]]
10 | input = "abc"
11 | output = "hex:e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"
12 |
13 | [[tests]]
14 | input = "message digest"
15 | output = "hex:18768bb4c48eb7fc88e5ddb17efcf2964abd7798a39d86a4b4a1e4c8"
16 |
17 | [[tests]]
18 | input = "abcdefghijklmnopqrstuvwxyz"
19 | output = "hex:5cdeca81e123f87cad96b9cba999f16f6d41549608d4e0f4681b8239"
20 |
21 | [[tests]]
22 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
23 | output = "hex:a67c289b8250a6f437a20137985d605589a8c163d45261b15419556e"
24 |
25 | [[tests]]
26 | input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
27 | output = "hex:0526898e185869f91b3e2a76dd72a15dc6940a67c8164a044cd25cc8"
28 |
29 | [[tests]]
30 | input = "The quick brown fox jumps over the lazy dog"
31 | output = "hex:d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795"
32 |
--------------------------------------------------------------------------------
/digest/tests/sha3/sha256.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
4 |
5 | [[tests]]
6 | input = "a"
7 | output = "hex:80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b"
8 |
9 | [[tests]]
10 | input = "abc"
11 | output = "hex:3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"
12 |
13 | [[tests]]
14 | input = "message digest"
15 | output = "hex:edcdb2069366e75243860c18c3a11465eca34bce6143d30c8665cefcfd32bffd"
16 |
17 | [[tests]]
18 | input = "abcdefghijklmnopqrstuvwxyz"
19 | output = "hex:7cab2dc765e21b241dbc1c255ce620b29f527c6d5e7f5f843e56288f0d707521"
20 |
21 | [[tests]]
22 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
23 | output = "hex:a79d6a9da47f04a3b9a9323ec9991f2105d4c78a7bc7beeb103855a7a11dfb9f"
24 |
25 | [[tests]]
26 | input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
27 | output = "hex:293e5ce4ce54ee71990ab06e511b7ccd62722b1beb414f5ff65c8274e0f5be1d"
28 |
29 | [[tests]]
30 | input = "The quick brown fox jumps over the lazy dog"
31 | output = "hex:69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04"
32 |
--------------------------------------------------------------------------------
/digest/tests/sha3/sha384.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"
4 |
5 | [[tests]]
6 | input = "a"
7 | output = "hex:1815f774f320491b48569efec794d249eeb59aae46d22bf77dafe25c5edc28d7ea44f93ee1234aa88f61c91912a4ccd9"
8 |
9 | [[tests]]
10 | input = "abc"
11 | output = "hex:ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"
12 |
13 | [[tests]]
14 | input = "message digest"
15 | output = "hex:d9519709f44af73e2c8e291109a979de3d61dc02bf69def7fbffdfffe662751513f19ad57e17d4b93ba1e484fc1980d5"
16 |
17 | [[tests]]
18 | input = "abcdefghijklmnopqrstuvwxyz"
19 | output = "hex:fed399d2217aaf4c717ad0c5102c15589e1c990cc2b9a5029056a7f7485888d6ab65db2370077a5cadb53fc9280d278f"
20 |
21 | [[tests]]
22 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
23 | output = "hex:d5b972302f5080d0830e0de7b6b2cf383665a008f4c4f386a61112652c742d20cb45aa51bd4f542fc733e2719e999291"
24 |
25 | [[tests]]
26 | input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
27 | output = "hex:3c213a17f514638acb3bf17f109f3e24c16f9f14f085b52a2f2b81adc0db83df1a58db2ce013191b8ba72d8fae7e2a5e"
28 |
29 | [[tests]]
30 | input = "The quick brown fox jumps over the lazy dog"
31 | output = "hex:7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41"
32 |
--------------------------------------------------------------------------------
/digest/tests/sha3/sha512.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"
4 |
5 | [[tests]]
6 | input = "a"
7 | output = "hex:697f2d856172cb8309d6b8b97dac4de344b549d4dee61edfb4962d8698b7fa803f4f93ff24393586e28b5b957ac3d1d369420ce53332712f997bd336d09ab02a"
8 |
9 | [[tests]]
10 | input = "abc"
11 | output = "hex:b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"
12 |
13 | [[tests]]
14 | input = "message digest"
15 | output = "hex:3444e155881fa15511f57726c7d7cfe80302a7433067b29d59a71415ca9dd141ac892d310bc4d78128c98fda839d18d7f0556f2fe7acb3c0cda4bff3a25f5f59"
16 |
17 | [[tests]]
18 | input = "abcdefghijklmnopqrstuvwxyz"
19 | output = "hex:af328d17fa28753a3c9f5cb72e376b90440b96f0289e5703b729324a975ab384eda565fc92aaded143669900d761861687acdc0a5ffa358bd0571aaad80aca68"
20 |
21 | [[tests]]
22 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
23 | output = "hex:d1db17b4745b255e5eb159f66593cc9c143850979fc7a3951796aba80165aab536b46174ce19e3f707f0e5c6487f5f03084bc0ec9461691ef20113e42ad28163"
24 |
25 | [[tests]]
26 | input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
27 | output = "hex:9524b9a5536b91069526b4f6196b7e9475b4da69e01f0c855797f224cd7335ddb286fd99b9b32ffe33b59ad424cc1744f6eb59137f5fb8601932e8a8af0ae930"
28 |
29 | [[tests]]
30 | input = "The quick brown fox jumps over the lazy dog"
31 | output = "hex:01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450"
32 |
--------------------------------------------------------------------------------
/digest/tests/tiger/mod.rs:
--------------------------------------------------------------------------------
1 | use digest::tiger::*;
2 |
3 | use utils;
4 |
5 | #[test]
6 | fn reference_implementation() {
7 | let suite = utils::load("./tests/tiger/tiger.toml");
8 |
9 | for test in suite.tests {
10 | test.test(Tiger::default());
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/digest/tests/tiger/tiger.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:60ef6c0dbc077b9c175ffb7771008c253bacea024c9d01ab"
4 | [[tests]]
5 | input = "abc"
6 | output = "hex:c79e799e14b53e7df935d83477fa4df939d18c44f76b73cd"
7 | [[tests]]
8 | input = "Tiger"
9 | output = "hex:a24ee9540c41d71b6a626f9ddf41d12e3031272b6aabbd9a"
10 | [[tests]]
11 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
12 | output = "hex:af58f9c05b886048c16f48bc904beffda838f005ff74035e"
13 | [[tests]]
14 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"
15 | output = "hex:76aa092e589b0f0b8b780944ad1f0c41c9a5ceb307d2fde0"
16 | [[tests]]
17 | input = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"
18 | output = "hex:82815d8924e2f11a88c0f292914c6cfdbfd8e78e2cf29ad0"
19 | [[tests]]
20 | input = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge."
21 | output = "hex:481f6dd0df57e103d7de0b663adb05f503b877f276adb286"
22 | [[tests]]
23 | input = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996."
24 | output = "hex:696d9960618847259f2fa580db2f955596d7bea2046f46d7"
25 | [[tests]]
26 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
27 | output = "hex:2720a38d7f0875545fd9614f48f7e67a92d37469da2ef378"
28 |
--------------------------------------------------------------------------------
/digest/tests/utils/mod.rs:
--------------------------------------------------------------------------------
1 | use std::path::Path;
2 | use std::fs::File;
3 | use std::io::Read;
4 |
5 | use toml;
6 |
7 | pub mod tests;
8 |
9 | #[derive(RustcDecodable)]
10 | pub struct Suite {
11 | pub tests: Vec,
12 | }
13 |
14 | pub fn load>(path: P) -> Suite {
15 | let mut content = String::new();
16 | File::open(path).and_then(|mut f| f.read_to_string(&mut content)).expect("Cannot read file");
17 |
18 | toml::decode_str(&content).expect("Cannot parse file")
19 | }
20 |
21 | #[macro_export]
22 | macro_rules! digest_quick {
23 | ($octavo:ty, $openssl:expr) => {
24 | #[test]
25 | fn quickcheck() {
26 | // use quickcheck::quickcheck;
27 |
28 | // fn prop(vec: Vec) -> bool {
29 | // use ::openssl::crypto::hash::{hash, Type};
30 | // use ::digest::Digest;
31 |
32 | // let octavo = {
33 | // let mut dig = <$octavo>::default();
34 | // let mut res = vec![0; <$octavo>::output_bytes()];
35 |
36 | // dig.update(&vec);
37 | // dig.result(&mut res[..]);
38 | // res
39 | // };
40 |
41 | // let openssl = hash($openssl, &vec);
42 |
43 | // octavo == openssl
44 | // }
45 |
46 | // quickcheck(prop as fn(Vec) -> bool)
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/digest/tests/utils/tests.rs:
--------------------------------------------------------------------------------
1 | use std::ops::Deref;
2 | use std::str;
3 |
4 | use digest::Digest;
5 | use rustc_serialize as ser;
6 | use rustc_serialize::hex::{FromHex, ToHex};
7 |
8 | #[derive(Debug, PartialEq, Eq)]
9 | pub struct Data(Vec);
10 | impl Deref for Data {
11 | type Target = [u8];
12 | fn deref(&self) -> &[u8] {
13 | &*self.0
14 | }
15 | }
16 |
17 | impl ser::Decodable for Data {
18 | fn decode(d: &mut D) -> Result {
19 | let data = try!(d.read_str());
20 |
21 | if data.starts_with("hex:") {
22 | Ok(Data(data[4..].from_hex().unwrap()))
23 | } else {
24 | Ok(Data(data.into()))
25 | }
26 | }
27 | }
28 |
29 | #[derive(RustcDecodable)]
30 | pub struct Test {
31 | input: Data,
32 | output: Data,
33 | }
34 |
35 | impl Test {
36 | pub fn test(&self, tested: T) {
37 | tested.test(self);
38 | }
39 | }
40 |
41 | pub trait Testable: Sized {
42 | fn test(self, &Test);
43 | }
44 |
45 | impl Testable for T
46 | where T: Digest + Sized
47 | {
48 | fn test(mut self, test: &Test) {
49 | self.update(&*test.input);
50 | let mut output = vec![0; T::output_bytes()];
51 | self.result(&mut output[..]);
52 | assert!(&*test.output == &output[..],
53 | "Input: {:?} (str: \"{}\")\nExpected: {}\nGot: {}",
54 | test.input,
55 | str::from_utf8(&*test.input).unwrap_or(""),
56 | test.output.to_hex(),
57 | output.to_hex());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/digest/tests/whirlpool/iso.toml:
--------------------------------------------------------------------------------
1 | [[tests]]
2 | input = ""
3 | output = "hex:19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3"
4 | [[tests]]
5 | input = "a"
6 | output = "hex:8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42d11bc645413aeff63a42391a39145a591a92200d560195e53b478584fdae231a"
7 | [[tests]]
8 | input = "abc"
9 | output = "hex:4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5"
10 | [[tests]]
11 | input = "message digest"
12 | output = "hex:378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b8421557659ef55c106b4b52ac5a4aaa692ed920052838f3362e86dbd37a8903e"
13 | [[tests]]
14 | input = "abcdefghijklmnopqrstuvwxyz"
15 | output = "hex:f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b08bf2a9251c30b6a0b8aae86177ab4a6f68f673e7207865d5d9819a3dba4eb3b"
16 | [[tests]]
17 | input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
18 | output = "hex:dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e08eba26629129d8fb7cb57211b9281a65517cc879d7b962142c65f5a7af01467"
19 | [[tests]]
20 | input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
21 | output = "hex:466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb6014294d5bd8df2a6c44e538cd047b2681a51a2c60481e88c5a20b2c2a80cf3a9a083b"
22 | [[tests]]
23 | input = "abcdbcdecdefdefgefghfghighijhijk"
24 | output = "hex:2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c6916bdc8031bc5be1b7b947639fe050b56939baaa0adff9ae6745b7b181c3be3fd"
25 |
--------------------------------------------------------------------------------
/digest/tests/whirlpool/mod.rs:
--------------------------------------------------------------------------------
1 | use digest::Digest;
2 | use digest::whirlpool::*;
3 |
4 | use utils;
5 |
6 | #[test]
7 | fn sample() {
8 | let mut digest = Whirlpool::default();
9 |
10 | digest.update("zażółć gęślą jaźń");
11 |
12 | let mut result = [0; 64];
13 |
14 | digest.result(&mut result[..]);
15 | }
16 |
17 | #[test]
18 | fn iso_test_vectors() {
19 | let suite = utils::load("./tests/whirlpool/iso.toml");
20 |
21 | for test in suite.tests {
22 | test.test(Whirlpool::default());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/docs/after.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docs/keys/hauleth.asc:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 | Version: GnuPG v1
3 |
4 | mQINBFYCjKcBEADu3B/xFTuQZYuwHZxBprA9BUVjIujHIVq0JYSKczHf8NlPR35o
5 | zaK4G8oze9GSc16j7/TE+4T+8PozCX9r3tN3xWBwhIYHLaMO9H3ZFck1UiWybKF7
6 | of4k7Kyy6vCHi6o7aaI5QxttFKofyPGRV3HS9tCWgV0Jpx4rdXrR8tFzsy67lSHn
7 | qlOn/z5uLLdk/qYDLUDplBhO+8QPgTPnZD/qxL7LAWTkIAyiBlu2KKXBDhpU3TTm
8 | DoRxiyNkfn6zK7/aGeSeRarXYgEg6H9sJrbukGBgB/GAdRQctKponz63UrX9uINu
9 | qdkEv2pZjMBbU55DvXPjQ6knq55uGJV3qh9/P9iiI5M3qiqqqHqE0xymArjTjXcI
10 | kfeq3ATmlGTaSPpAqiNTMubbUc+5P4eSa6qSPPc4nCtPllPhZqsEfm3PAL87P4oh
11 | wc13+zUfjFnJX2IdEzOyxG+ICyRQdz84u4JmSdU31qCvG/VY6xiO93U2qy+5fxwE
12 | YKDyJ6KivdYkfHjFso4CXDO1o4RmvzjTekMW5HCaoY+goyYghmH89aOLtkuxeuBb
13 | TyrADotSYBClP3DfSqna5sbdk3ieP7FRWYq/srFWmhDQeXSd/0khThCE3GKzasly
14 | P8BUPy+WWYA9184gZsdoTurGJW2+UEAVweLzvyosDf04aIPKHGL2Nv+meQARAQAB
15 | tCfFgXVrYXN6IEphbiBOaWVtaWVyIDxsdWthc3pAbmllbWllci5wbD6JAj4EEwEC
16 | ACgFAlYCjKcCGwMFCQHhM4AGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPDo
17 | jMtEW2Zcd9kP/0s93QRHC4Qg5ksuRTEj1YDZmYuqLOb7RZzlwca/fbNJEbezHygJ
18 | Qt+Rt3RpEXtrmDkqwWJ9N9tswfhCPrHA8wCMLiO6GQ69e8E9oPhYkjA1rvbaQY9F
19 | NDvP2qTPpZZIHWeE4Ni8TlofGbddeUgP0NuvCb2CAbDw6JmSBglNVefPCRFRng3f
20 | 85EJZQHeMhdBY9EbW21eWfJ/6Z39PoClwOMvN3WVuPZk7Ms8jebbojZoRlRg2m3u
21 | 5HUJ7SD0is5xYm7VwIKcHMXeOtUbtM8mxJmYTu7Pdf00CNXayhBmVwlHlIRklFdN
22 | N/uqmO80uI3IuIXH67E7Q5pBk/4dtg/agCPxjU9uNvxhHImyMQKEgTXY0ZEqSUr+
23 | 3G9SIYUAliNWkF1wq9HZm2q/kIeIavniNTOD8v/R/9cFNKnm2NQy0l8yYBp6CMQk
24 | 4cN+BNPyeI0bAGYSdajKfFvRQosKS6nQWSWl9s4dB9AImOFDXQIqTYhC2UCIGaN+
25 | igDAObIYmOZYEXNHHyJN5AEYFrsSca/g7sfne8FYqY5hJIs5TMuKf9WkQy+BDuPI
26 | l/cxG2lUrd4A4igIiMlArR++qEPOO4/N4RXrGOFhtsTkvFo0TOiEDkMIn/+WdFl+
27 | mEmsPqfRVuOnQFxskqe21cg7e8EBC6L+upU/BczWPUi59HsI0qi4/EuAuQINBFYC
28 | jKcBEADRNaOVQ4fnDpDKKZh5P+4ClmTP5d4YHFO4LdeQlrTC8teR+rmbPWzfyxO6
29 | sMsJthmIZIlXDOw4F3vi+bZm9BlnkSaTfITOYYjq1Fa4AQ7FqfjpZblQCXxEb1I8
30 | HLUycMecMBCF7LPmyUpR0+VkL0q/4zUbaa/ou/eSb4FM6rkBVestBjbULXzDrKez
31 | RwI8tzThli4swwFTgnZh6fd3HqZ/ZTplA3IUt9dr8Ec4E5QB1EfNx4JDy64JQ8OI
32 | RRvRRmYgaPx3QiVTX3fnzRVsHWBBEV4vqYCVi/HhT24NpFgpnbTRbfwAPyXWP2Ii
33 | FE3I2d6mOAfk4/n+M3T9qCwmpqrl39JJyTL+BW8FMw+T4hJVfDR+NLokXtkTq3KW
34 | a8GWcHnPpAYlmW8q1xIHpZwh9gjkcGXvJo1V3HhrBaKkZ192+EayUc35Nu6x6pNG
35 | OQvWr0x7XTx/5AbIgzzrItyKMfuE+SFj8CfAVJ1hn+2OFbyZPmTErtkyo9JymL98
36 | epHqD8juso2iPDS8fW0FJq2Zv/BJPciONIlpdMFkqM3es3ua939g/uNagojZ34PC
37 | rtQzbK2vSqmh6l2qLaxsD5GBlxAhN8I9JdfnP1kYYxRomRd8qB5GTZXmcZ38Bgvh
38 | 8GQ/Pm6purxi55rOOWsQRVtMPtyhQsvCCuntIYermxSeSOswQQARAQABiQIlBBgB
39 | AgAPBQJWAoynAhsMBQkB4TOAAAoJEPDojMtEW2ZcLfQP/RqUG5t6ZLmon3ayIPp8
40 | ofOIU9mHp91KCvmSTJlLzvKAW4zZrB57VF1eP4KKoUCHitarvRnQFeX/T1Ovp0pC
41 | 7RUz+lIft3NC4wp2hy+PowkkOWqp1d4ryj8x3BKL0DcyTq/ed5k0sr5e/21Bm//z
42 | sZou1lJSQW8KtnGoT/5wcmi/eQ3f2TUcGjAwQCF8MPCgrzNnrmelCEYXt1qqFd17
43 | q2CiOo70ARRgGCIiSbm3vdsKpG4mjGAkmg4Q3qtZW96ihBeyjvXolIPtYf1lfQG+
44 | UHXrwqYFgwzrJmN90JfpIO8a6UmNKiYcXpCEeLU+P4pvWf+HLkWSlO/wdZ7FpSs7
45 | 1l9l5fN0fyvv3j22ItT8U9Lz0tkMe//fbQ5DNpzpD+q9ETVwSQvFzKlRx3KxhLT/
46 | V9VGRjnfKavntrg8K03EKDVj5BgpawOuqkOklWO6zYJPtXKqNBqA5CjksbrHC2RE
47 | 6xIh3l+ImiSle3p+yPsseZSYdece3M9mr1C1Ew94FDWwkabayD44tdassJD9cfBd
48 | LQZ4CKwA5m+lNrGcFCu616ybDzPIHmhbaMNdyNcJEVVAZo+d1xoSC2yJ4EC0hUwf
49 | LExjZ8ugOR+Vdz/zWN994Vrbkq5YbLwX+ylePvy6z/+9O2nNyTS/omLqKcL9Q2st
50 | qogz8YbawbVc4KWn0aE5n3IL
51 | =yN2S
52 | -----END PGP PUBLIC KEY BLOCK-----
53 |
--------------------------------------------------------------------------------
/docs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libOctavo/octavo/2eff2009fc988371bf1588c2e000b036d2a35372/docs/logo.png
--------------------------------------------------------------------------------
/docs/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
63 |
--------------------------------------------------------------------------------
/examples/sums.rs:
--------------------------------------------------------------------------------
1 | extern crate octavo;
2 |
3 | use std::io::Write;
4 |
5 | use octavo::digest::prelude::*;
6 |
7 | fn hex, D: Digest>(data: T, mut digest: D) -> String {
8 | digest.update(data);
9 |
10 | let mut result = vec![0; D::output_bytes()];
11 |
12 | digest.result(&mut result[..]);
13 |
14 | let mut out = vec![0; D::output_bytes() * 2];
15 |
16 | for byte in result {
17 | write!(&mut out, "{:02x}", byte).unwrap();
18 | }
19 |
20 | String::from_utf8(out).unwrap()
21 | }
22 |
23 | fn main() {
24 | let data = "octavo";
25 |
26 | println!("MD5: {}", hex(&data, Md5::default()));
27 | println!("RIPEMD-160: {}", hex(&data, Ripemd160::default()));
28 | println!("SHA-1: {}", hex(&data, Sha1::default()));
29 | println!("SHA-224: {}", hex(&data, sha2::Sha224::default()));
30 | println!("SHA-256: {}", hex(&data, sha2::Sha256::default()));
31 | println!("SHA-384: {}", hex(&data, sha2::Sha384::default()));
32 | println!("SHA-512: {}", hex(&data, sha2::Sha512::default()));
33 | println!("SHA-512/224: {}", hex(&data, sha2::Sha512224::default()));
34 | println!("SHA-512/256: {}", hex(&data, sha2::Sha512256::default()));
35 | println!("SHA3-224: {}", hex(&data, sha3::Sha224::default()));
36 | println!("SHA3-256: {}", hex(&data, sha3::Sha256::default()));
37 | println!("SHA3-384: {}", hex(&data, sha3::Sha384::default()));
38 | println!("SHA3-512: {}", hex(&data, sha3::Sha512::default()));
39 | println!("Blake2s128: {}", hex(&data, blake2::Blake2s128::default()));
40 | println!("Blake2s160: {}", hex(&data, blake2::Blake2s160::default()));
41 | println!("Blake2s224: {}", hex(&data, blake2::Blake2s224::default()));
42 | println!("Blake2s256: {}", hex(&data, blake2::Blake2s256::default()));
43 | println!("Blake2b160: {}", hex(&data, blake2::Blake2b160::default()));
44 | println!("Blake2b256: {}", hex(&data, blake2::Blake2b256::default()));
45 | println!("Blake2b384: {}", hex(&data, blake2::Blake2b384::default()));
46 | println!("Blake2b512: {}", hex(&data, blake2::Blake2b512::default()));
47 | println!("Tiger: {}", hex(&data, tiger::Tiger::default()));
48 | println!("Tiger2: {}", hex(&data, tiger::Tiger2::default()));
49 | println!("WHIRLPOOL: {}", hex(&data, Whirlpool::default()));
50 | }
51 |
--------------------------------------------------------------------------------
/kdf/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ["Łukasz Jan Niemier "]
3 | homepage = "http://liboctavo.github.io/"
4 | documentation = "http://liboctavo.github.io/octavo/octavo_kdf"
5 | repository = "https://github.com/libOctavo/octavo"
6 | readme = "README.md"
7 | name = "octavo-kdf"
8 | description = "Octavo - Key Derivation Functions. WARNING!!! Not suitable for production"
9 | keywords = [
10 | "bcrypt", "kdf", "passwords"
11 | ]
12 | license = "MIT"
13 | version = "0.1.1"
14 |
15 | [dependencies]
16 | byteorder = "0.4.2"
17 |
18 | [dependencies.octavo-crypto]
19 | path = "../crypto"
20 | version = "0.1.0"
21 |
22 | [features]
23 | unstable = []
24 |
--------------------------------------------------------------------------------
/kdf/src/bcrypt.rs:
--------------------------------------------------------------------------------
1 | use byteorder::{ByteOrder, BigEndian};
2 |
3 | use crypto::block::blowfish::Blowfish;
4 |
5 | fn bcrypt_setup(cost: usize, salt: &[u8], key: &[u8]) -> Blowfish {
6 | let mut state = Blowfish::init().salted_expand_key(salt, key);
7 |
8 | for _ in 0..(1 << cost) {
9 | state = state.expand_key(key).expand_key(salt);
10 | }
11 |
12 | state
13 | }
14 |
15 | pub fn bcrypt, I: AsRef<[u8]>, O: AsMut<[u8]>>(cost: usize,
16 | salt: S,
17 | input: I,
18 | mut output: O) {
19 | assert_eq!(salt.as_ref().len(), 16);
20 | assert!(0 < input.as_ref().len() && input.as_ref().len() <= 72);
21 | assert_eq!(output.as_mut().len(), 24);
22 |
23 | let mut output = output.as_mut();
24 |
25 | let state = bcrypt_setup(cost, salt.as_ref(), input.as_ref());
26 | let mut ctext = [0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, 0x6f756274];
27 | for (chunk, out) in ctext.chunks_mut(2).zip(output.chunks_mut(8)) {
28 | for _ in 0..64 {
29 | let (l, r) = state.encrypt_round((chunk[0], chunk[1]));
30 | chunk[0] = l;
31 | chunk[1] = r;
32 | }
33 | BigEndian::write_u32(&mut out[0..4], chunk[0]);
34 | BigEndian::write_u32(&mut out[4..8], chunk[1]);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/kdf/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
2 | html_root_url = "http://libOctavo.github.io/")]
3 |
4 | extern crate octavo_crypto as crypto;
5 | extern crate byteorder;
6 |
7 | pub mod bcrypt;
8 |
--------------------------------------------------------------------------------
/mac/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ["Łukasz Jan Niemier "]
3 | description = "Octavo - Message Authentication Codes. WARNING!!! Not suitable for production"
4 | documentation = "http://liboctavo.github.io/octavo/octavo_kdf"
5 | homepage = "http://liboctavo.github.io/"
6 | keywords = ["mac", "hmac", "authentication"]
7 | license = "MIT"
8 | name = "octavo-mac"
9 | readme = "README.md"
10 | repository = "https://github.com/libOctavo/octavo"
11 | version = "0.1.1"
12 |
13 | [dependencies]
14 | generic-array = "0.2.0"
15 |
16 | [dependencies.octavo-digest]
17 | path = "../digest"
18 | version = "0.1.0"
19 |
20 | [dev-dependencies]
21 | openssl = "0.8.2"
22 | quickcheck = "0.3.1"
23 |
24 | [features]
25 | unstable = []
26 |
--------------------------------------------------------------------------------
/mac/src/hmac.rs:
--------------------------------------------------------------------------------
1 | use digest::Digest;
2 | use generic_array::GenericArray;
3 |
4 | use Mac;
5 |
6 | const IPAD: u8 = 0x36;
7 | const OPAD: u8 = 0x5c;
8 |
9 | pub struct Hmac {
10 | inner: T,
11 | outer: T,
12 | }
13 |
14 | impl Hmac {
15 | pub fn new>(key: K) -> Self {
16 | Self::with_digest(key.as_ref(), Default::default())
17 | }
18 | }
19 |
20 | impl Hmac {
21 | pub fn with_digest(key: &[u8], digest: T) -> Self {
22 | let mut inner = digest.clone();
23 | let mut outer = digest.clone();
24 |
25 | let key = Self::expand_key(key, digest);
26 | for byte in key.iter() {
27 | inner.update(&[byte ^ IPAD]);
28 | outer.update(&[byte ^ OPAD]);
29 | }
30 |
31 | Hmac {
32 | inner: inner,
33 | outer: outer,
34 | }
35 | }
36 |
37 | fn expand_key(key: &[u8], mut digest: T) -> GenericArray {
38 | let bs = T::block_size();
39 | let mut exp_key = GenericArray::new();
40 |
41 | if key.len() <= bs {
42 | for i in 0..key.len() {
43 | exp_key[i] = key[i];
44 | }
45 | } else {
46 | digest.update(key);
47 | digest.result(&mut exp_key[..]);
48 | }
49 |
50 | exp_key
51 | }
52 | }
53 |
54 | impl Mac for Hmac {
55 | fn update>(&mut self, data: D) {
56 | self.inner.update(data)
57 | }
58 |
59 | fn output_bits() -> usize {
60 | T::output_bits()
61 | }
62 | fn block_size() -> usize {
63 | T::block_size()
64 | }
65 |
66 | fn result>(mut self, mut output: O) {
67 | self.inner.result(output.as_mut());
68 |
69 | self.outer.update(output.as_mut());
70 | self.outer.result(output.as_mut());
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/mac/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
2 | html_root_url = "http://libOctavo.github.io/")]
3 |
4 | extern crate octavo_digest as digest;
5 | extern crate generic_array;
6 |
7 | pub mod hmac;
8 |
9 | pub trait Mac: Sized {
10 | fn update>(&mut self, data: D);
11 |
12 | /// Output size in bits
13 | fn output_bits() -> usize;
14 | /// Output size in bytes
15 | fn output_bytes() -> usize {
16 | (Self::output_bits() + 7) / 8
17 | }
18 | fn block_size() -> usize;
19 |
20 | /// Write resulting hash into `output`.
21 | ///
22 | /// `output` should be big enough to contain whole output.
23 | ///
24 | /// ## Panics
25 | ///
26 | /// If output length is less than `MAC::output_bytes`.
27 | fn result(self, output: T) where T: AsMut<[u8]>;
28 | }
29 |
--------------------------------------------------------------------------------
/mac/tests/hmac.rs:
--------------------------------------------------------------------------------
1 | extern crate octavo_mac as mac;
2 | extern crate octavo_digest as digest;
3 |
4 | mod md5 {
5 | use mac::Mac;
6 | use mac::hmac::Hmac;
7 |
8 | use digest::prelude::*;
9 |
10 | #[test]
11 | fn rfc2104_test_vector_1() {
12 | let mut hmac_md5 = Hmac::::new(&[0x0b; 16]);
13 | hmac_md5.update("Hi There");
14 |
15 | let mut output = [0; 16];
16 |
17 | hmac_md5.result(&mut output);
18 |
19 | assert_eq!([0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15,
20 | 0x8b, 0xfc, 0x9d],
21 | output);
22 | }
23 |
24 | #[test]
25 | fn rfc2104_test_vector_2() {
26 | let mut hmac_md5 = Hmac::::new("Jefe");
27 | hmac_md5.update("what do ya want for nothing?");
28 |
29 | let mut output = [0; 16];
30 |
31 | hmac_md5.result(&mut output);
32 |
33 | assert_eq!([0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a,
34 | 0x5d, 0xb7, 0x38],
35 | output);
36 | }
37 |
38 | #[test]
39 | fn rfc2104_test_vector_3() {
40 | let mut hmac_md5 = Hmac::::new(&[0xaa; 16]);
41 | for _ in 0..50 {
42 | hmac_md5.update(&[0xdd]);
43 | }
44 |
45 | let mut output = [0; 16];
46 |
47 | hmac_md5.result(&mut output);
48 |
49 | assert_eq!([0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0,
50 | 0xe8, 0xb3, 0xf6],
51 | output);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! Highly modular & configurable hash & crypto library written in Rust
2 | //!
3 | //! # About
4 | //!
5 | //! Octavo is Rust implementation of cryptographic primitives and [Transport Layer Security][tls].
6 | //! Our goal is to provide safe, fast, full-featured and configurable cryptographic library
7 | //! for modern world.
8 | //!
9 | //! Except of Rust API we want expose also C API for usage with other languages and tools. Probably
10 | //! there will also land thin [OpenSSL][openssl] compatibility cascade for use with existing code.
11 | //!
12 | //! [tls]: https://en.wikipedia.org/wiki/Transport_Layer_Security "Transport Layer Security"
13 | //!
14 | //! ## Legalities
15 | //!
16 | //! Please remember that export/import and/or use of strong cryptography software, providing
17 | //! cryptography hooks, or even just communicating technical details about cryptography software is
18 | //! illegal in some parts of the world. So when you import this package to your country,
19 | //! re-distribute it from there or even just email technical suggestions or even source patches to
20 | //! the authors or other people you are strongly advised to pay close attention to any laws or
21 | //! regulations which apply to you. The authors of Octavo are not liable for any violations you
22 | //! make here. So be careful, it is your responsibility.[^authors]
23 | //!
24 | //! [^authors]: Text of this paragraph is copied from [OpenSSL website][openssl].
25 | //! [openssl]: http://www.openssl.org/ "OpenSSL - Cryptography and SSL/TLS Toolkit"
26 |
27 | #![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
28 | html_root_url = "http://libOctavo.github.io/")]
29 |
30 | #[cfg(feature = "octavo-crypto")]
31 | pub extern crate octavo_crypto;
32 | #[cfg(feature = "octavo-digest")]
33 | pub extern crate octavo_digest;
34 | #[cfg(feature = "octavo-kdf")]
35 | pub extern crate octavo_kdf;
36 | #[cfg(feature = "octavo-mac")]
37 | pub extern crate octavo_mac;
38 |
39 | #[cfg(feature = "octavo-crypto")]
40 | pub use octavo_crypto as crypto;
41 | #[cfg(feature = "octavo-digest")]
42 | pub use octavo_digest as digest;
43 | #[cfg(feature = "octavo-kdf")]
44 | pub use octavo_kdf as kdf;
45 | #[cfg(feature = "octavo-mac")]
46 | pub use octavo_mac as mac;
47 |
--------------------------------------------------------------------------------
/tests/kdf/mod.rs:
--------------------------------------------------------------------------------
1 | mod bcrypt;
2 |
--------------------------------------------------------------------------------
/tests/lib.rs:
--------------------------------------------------------------------------------
1 | extern crate octavo;
2 |
3 | mod kdf;
4 |
--------------------------------------------------------------------------------
/tools/doc-upload.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -o errexit -o nounset
4 |
5 | if [ "$TRAVIS_BRANCH" != "master" ] || [ "$TRAVIS_PULL_REQUEST" != false ]
6 | then
7 | echo "This commit was made against the $TRAVIS_BRANCH and not the master! No deploy!"
8 | exit 0
9 | fi
10 |
11 | rev=$(git rev-parse --short HEAD)
12 |
13 | cd target/doc
14 |
15 | git init
16 | git config user.name "Łukasz Niemier"
17 | git config user.email "lukasz@niemier.pl"
18 |
19 | git remote add upstream "https://$GH_TOKEN@github.com/libOctavo/octavo.git"
20 | git fetch upstream
21 | git reset upstream/gh-pages
22 |
23 | touch .
24 |
25 | git add -A .
26 | git commit -m "Documentation for ${rev}"
27 | git push -q upstream HEAD:gh-pages
28 |
--------------------------------------------------------------------------------
/tools/stackcollapse:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl -w
2 | #
3 | # stackcolllapse-perf.pl collapse perf samples into single lines.
4 | #
5 | # Parses a list of multiline stacks generated by "perf script", and
6 | # outputs a semicolon separated stack followed by a space and a count.
7 | # If memory addresses (+0xd) are present, they are stripped, and resulting
8 | # identical stacks are colased with their counts summed.
9 | #
10 | # USAGE: ./stackcollapse-perf.pl [options] infile > outfile
11 | #
12 | # Run "./stackcollapse-perf.pl -h" to list options.
13 | #
14 | # Example input:
15 | #
16 | # swapper 0 [000] 158665.570607: cpu-clock:
17 | # ffffffff8103ce3b native_safe_halt ([kernel.kallsyms])
18 | # ffffffff8101c6a3 default_idle ([kernel.kallsyms])
19 | # ffffffff81013236 cpu_idle ([kernel.kallsyms])
20 | # ffffffff815bf03e rest_init ([kernel.kallsyms])
21 | # ffffffff81aebbfe start_kernel ([kernel.kallsyms].init.text)
22 | # [...]
23 | #
24 | # Example output:
25 | #
26 | # swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 1
27 | #
28 | # Input may be created and processed using:
29 | #
30 | # perf record -a -g -F 997 sleep 60
31 | # perf script | ./stackcollapse-perf.pl > out.stacks-folded
32 | #
33 | # The output of "perf script" should include stack traces. If these are missing
34 | # for you, try manually selecting the perf script output; eg:
35 | #
36 | # perf script -f comm,pid,tid,cpu,time,event,ip,sym,dso,trace | ...
37 | #
38 | # This is also required for the --pid or --tid options, so that the output has
39 | # both the PID and TID.
40 | #
41 | # Copyright 2012 Joyent, Inc. All rights reserved.
42 | # Copyright 2012 Brendan Gregg. All rights reserved.
43 | #
44 | # CDDL HEADER START
45 | #
46 | # The contents of this file are subject to the terms of the
47 | # Common Development and Distribution License (the "License").
48 | # You may not use this file except in compliance with the License.
49 | #
50 | # You can obtain a copy of the license at docs/cddl1.txt or
51 | # http://opensource.org/licenses/CDDL-1.0.
52 | # See the License for the specific language governing permissions
53 | # and limitations under the License.
54 | #
55 | # When distributing Covered Code, include this CDDL HEADER in each
56 | # file and include the License file at docs/cddl1.txt.
57 | # If applicable, add the following below this CDDL HEADER, with the
58 | # fields enclosed by brackets "[]" replaced with your own identifying
59 | # information: Portions Copyright [yyyy] [name of copyright owner]
60 | #
61 | # CDDL HEADER END
62 | #
63 | # 02-Mar-2012 Brendan Gregg Created this.
64 | # 02-Jul-2014 " " Added process name to stacks.
65 |
66 | use strict;
67 | use Getopt::Long;
68 |
69 | my %collapsed;
70 |
71 | sub remember_stack {
72 | my ($stack, $count) = @_;
73 | $collapsed{$stack} += $count;
74 | }
75 | my $annotate_kernel = 0; # put an annotation on kernel function
76 | my $include_pname = 1; # include process names in stacks
77 | my $include_pid = 0; # include process ID with process name
78 | my $include_tid = 0; # include process & thread ID with process name
79 | my $tidy_java = 1; # condense Java signatures
80 | my $tidy_generic = 1; # clean up function names a little
81 | my $target_pname; # target process name from perf invocation
82 |
83 | my $show_inline = 0;
84 | my $show_context = 0;
85 | GetOptions('inline' => \$show_inline,
86 | 'context' => \$show_context,
87 | 'pid' => \$include_pid,
88 | 'kernel' => \$annotate_kernel,
89 | 'tid' => \$include_tid)
90 | or die < outfile\n
92 | --pid # include PID with process names [1]
93 | --tid # include TID and PID with process names [1]
94 | --inline # un-inline using addr2line
95 | --kernel # annotate kernel functions with a _[k]
96 | --context # include source context from addr2line\n
97 | [1] perf script must emit both PID and TIDs for these to work; eg:
98 | perf script -f comm,pid,tid,cpu,time,event,ip,sym,dso,trace
99 | USAGE_END
100 |
101 | # for the --inline option
102 | sub inline {
103 | my ($pc, $mod) = @_;
104 |
105 | # capture addr2line output
106 | my $a2l_output = `addr2line -a $pc -e $mod -i -f -s -C`;
107 |
108 | # remove first line
109 | $a2l_output =~ s/^(.*\n){1}//;
110 |
111 | my @fullfunc;
112 | my $one_item = "";
113 | for (split /^/, $a2l_output) {
114 | chomp $_;
115 |
116 | # remove discriminator info if exists
117 | $_ =~ s/ \(discriminator \S+\)//;
118 |
119 | if ($one_item eq "") {
120 | $one_item = $_;
121 | } else {
122 | if ($show_context == 1) {
123 | unshift @fullfunc, $one_item . ":$_";
124 | } else {
125 | unshift @fullfunc, $one_item;
126 | }
127 | $one_item = "";
128 | }
129 | }
130 |
131 | return join(";", @fullfunc);
132 | }
133 |
134 | my @stack;
135 | my $pname;
136 |
137 | #
138 | # Main loop
139 | #
140 | while (defined($_ = <>)) {
141 |
142 | # find the name of the process launched by perf, by stepping backwards
143 | # over the args to find the first non-option (no dash):
144 | if (/^# cmdline/) {
145 | my @args = split ' ', $_;
146 | foreach my $arg (reverse @args) {
147 | if ($arg !~ /^-/) {
148 | $target_pname = $arg;
149 | $target_pname =~ s:.*/::; # strip pathname
150 | last;
151 | }
152 | }
153 | }
154 |
155 | # skip remaining comments
156 | next if m/^#/;
157 | chomp;
158 |
159 | # end of stack. save cached data.
160 | if (m/^$/) {
161 | if ($include_pname) {
162 | if (defined $pname) {
163 | unshift @stack, $pname;
164 | } else {
165 | unshift @stack, "";
166 | }
167 | }
168 | remember_stack(join(";", @stack), 1) if @stack;
169 | undef @stack;
170 | undef $pname;
171 | next;
172 | }
173 |
174 | # event record start
175 | if (/^(\S+\s*?\S*?)\s+(\d+)\s/) {
176 | # default "perf script" output has TID but not PID
177 | # eg, "java 25607 4794564.109216: cycles:"
178 | # eg, "java 12688 [002] 6544038.708352: cpu-clock:"
179 | # eg, "V8 WorkerThread 25607 4794564.109216: cycles:"
180 | # other combinations possible
181 | if ($include_tid) {
182 | $pname = "$1-?/$2";
183 | } elsif ($include_pid) {
184 | $pname = "$1-?";
185 | } else {
186 | $pname = $1;
187 | }
188 | $pname =~ tr/ /_/;
189 | } elsif (/^(\S+\s*?\S*?)\s+(\d+)\/(\d+)/) {
190 | # eg, "java 24636/25607 [000] 4794564.109216: cycles:"
191 | # eg, "java 12688/12764 6544038.708352: cpu-clock:"
192 | # eg, "V8 WorkerThread 24636/25607 [000] 94564.109216: cycles:"
193 | # other combinations possible
194 | if ($include_tid) {
195 | $pname = "$1-$2/$3";
196 | } elsif ($include_pid) {
197 | $pname = "$1-$2";
198 | } else {
199 | $pname = $1;
200 | }
201 | $pname =~ tr/ /_/;
202 |
203 | # stack line
204 | } elsif (/^\s*(\w+)\s*(.+) \((\S*)\)/) {
205 | my ($pc, $func, $mod) = ($1, $2, $3);
206 | $func.="_[k]" if ($annotate_kernel == 1 && $mod =~ m/kernel.kall/);
207 | if ($show_inline == 1 && index($mod, $target_pname) != -1) {
208 | unshift @stack, inline($pc, $mod);
209 | next;
210 | }
211 |
212 | next if $func =~ /^\(/; # skip process names
213 |
214 | if ($tidy_generic) {
215 | $func =~ s/;/:/g;
216 | $func =~ tr/<>//d;
217 | $func =~ s/\(.*//;
218 | # now tidy this horrible thing:
219 | # 13a80b608e0a RegExp:[&<>\"\'] (/tmp/perf-7539.map)
220 | $func =~ tr/"\'//d;
221 | # fall through to $tidy_java
222 | }
223 |
224 | if ($tidy_java and $pname eq "java") {
225 | # along with $tidy_generic, converts the following:
226 | # Lorg/mozilla/javascript/ContextFactory;.call(Lorg/mozilla/javascript/ContextAction;)Ljava/lang/Object;
227 | # Lorg/mozilla/javascript/ContextFactory;.call(Lorg/mozilla/javascript/C
228 | # Lorg/mozilla/javascript/MemberBox;.(Ljava/lang/reflect/Method;)V
229 | # into:
230 | # org/mozilla/javascript/ContextFactory:.call
231 | # org/mozilla/javascript/ContextFactory:.call
232 | # org/mozilla/javascript/MemberBox:.init
233 | $func =~ s/^L// if $func =~ m:/:;
234 | }
235 |
236 | unshift @stack, $func;
237 | } else {
238 | warn "Unrecognized line: $_";
239 | }
240 | }
241 |
242 | foreach my $k (sort { $a cmp $b } keys %collapsed) {
243 | print "$k $collapsed{$k}\n";
244 | }
245 |
--------------------------------------------------------------------------------