1extern crate crossbeam;
2extern crate num_cpus;
3#[macro_use]
4extern crate lazy_static;
5
6lazy_static!{}
8
9pub mod prelude;
10
11#[cfg(test)]
12mod tests {
13 extern crate md5;
14 extern crate rand;
15
16 use prelude::{Hasher, Reducer, RainbowTable};
17 use self::rand::{thread_rng, Rng};
18
19 struct MD5Hasher;
21 impl Hasher for MD5Hasher {
22 fn digest(&self, plaintext : &str) -> String {
23 format!("{:x}", md5::compute(plaintext.as_bytes()))
24 }
25 }
26
27 struct SubstringReducer {
29 n: usize
30 }
31 impl Reducer for SubstringReducer {
32 fn reduce(&self, hash : &str) -> String {
33 String::from(&hash[..self.n])
34 }
35 }
36
37 lazy_static! {
38 static ref TABLE : RainbowTable<MD5Hasher, SubstringReducer> = {
39 let mut rfs : Vec<SubstringReducer> = Vec::new();
41 for i in 6..27 {
42 rfs.push(SubstringReducer { n : i });
43 }
44
45 let mut table : RainbowTable<MD5Hasher, SubstringReducer> = RainbowTable::new(MD5Hasher, rfs);
47
48 for i in 0..1000 {
50 table.add_seed(format!("{}", i));
51 }
52
53 table
54 };
55 }
56
57 #[test]
58 fn test_rainbow_table_find_seeds() {
59 for i in 0..1000 {
61 let seed = format!("{}", i);
62 let seed_hash = format!("{:x}", md5::compute(seed.as_bytes()));
63 assert_eq!(Some(seed), TABLE.find_plaintext(&seed_hash));
64 }
65 }
66
67 #[test]
68 fn test_rainbow_table_find_random() {
69 let mut rfs : Vec<SubstringReducer> = Vec::new();
71 let hf = MD5Hasher;
72 for i in 6..27 {
73 rfs.push(SubstringReducer { n : i });
74 }
75
76 let mut rng = thread_rng();
78 for _ in 0..1000 {
79 let mut value = format!("{}", rng.gen_range(0, 1000));
80 let reductions = rng.gen_range(1, rfs.len());
81 for i in 0..reductions {
82 value = rfs[i].reduce(&hf.digest(&value[..])[..]);
83 }
84 let mut hash = hf.digest(&value[..]);
85 assert_eq!(Some(value), TABLE.find_plaintext(&hash));
86 }
87 }
88
89 #[test]
90 fn test_rainbow_table_find_none() {
91 assert_eq!(None, TABLE.find_plaintext("8a1fb399dcf220db935995abce6a1532"));
93 }
94}
95