diff --git a/2016/14/Cargo.lock b/2016/14/Cargo.lock new file mode 100644 index 0000000..dd2b1bd --- /dev/null +++ b/2016/14/Cargo.lock @@ -0,0 +1,81 @@ +[root] +name = "14" +version = "0.1.0" +dependencies = [ + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" +"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" +"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" +"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/2016/14/Cargo.toml b/2016/14/Cargo.toml new file mode 100644 index 0000000..3641134 --- /dev/null +++ b/2016/14/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "14" +version = "0.1.0" +authors = ["logaritmisk "] + +[dependencies] +rust-crypto = "0.2" diff --git a/2016/14/src/main.rs b/2016/14/src/main.rs new file mode 100644 index 0000000..6ebe44a --- /dev/null +++ b/2016/14/src/main.rs @@ -0,0 +1,137 @@ +extern crate crypto; + +use crypto::md5::Md5; +use crypto::digest::Digest; + + +pub struct Hasher { + md5: Md5, + index: u64, + secret: String, + stretch: usize +} + +impl Hasher { + pub fn new(secret: &str, stretch: usize) -> Self { + Hasher { + md5: Md5::new(), + index: 0, + secret: secret.to_owned(), + stretch: stretch + } + } +} + +impl Iterator for Hasher { + type Item = String; + + fn next(&mut self) -> Option { + let mut input = format!("{}{}", self.secret, self.index); + + for _ in 0..self.stretch + 1 { + self.md5.reset(); + self.md5.input(input.as_bytes()); + + input = self.md5.result_str(); + } + + self.index += 1; + + Some(input) + } +} + +pub fn find_triplet(input: &str) -> Option { + let m = input.as_bytes().windows(3).find(|&x| x[0] == x[1] && x[1] == x[2]); + + match m { + Some(chars) => Some(chars[0] as char), + None => None + } +} + +pub fn contains_sequence(input: &str, needle: char, length: usize) -> bool { + input.contains(&vec![needle; length].into_iter().collect::()) +} + +fn generate(salt: &str, stretch: usize) -> Vec<(String, char, usize)> { + let mut data: Vec<(String, char, usize)> = Vec::new(); + let mut keys = Vec::new(); + + 'main: for (i, hash) in Hasher::new(salt, stretch).enumerate() { + data.retain(|&(_, _, n)| n + 1000 > i); + + { + while let Some(position) = data.iter() + .position(|&(_, c, _)| contains_sequence(&hash, c, 5)) + { + keys.push(data.remove(position)); + + if keys.len() == 64 { + break 'main; + } + } + } + + if let Some(c) = find_triplet(&hash) { + data.push((hash.clone(), c, i)); + } + } + + keys.sort_by_key(|&(_, _, n)| n); + + keys +} + + +fn main() { + let keys_1 = generate("jlmsuwbz", 0); + + println!("keys_1={:#?}", keys_1); + + let keys_2 = generate("jlmsuwbz", 2016); + + println!("keys_2={:#?}", keys_2); +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_triplet() { + assert_eq!(Some('8'), find_triplet("cc38887a5")); + assert_eq!(Some('e'), find_triplet("cc3eee7a5")); + + assert_eq!(None, find_triplet("cc3887a5")); + assert_eq!(None, find_triplet("cc3ee7a5")); + } + + #[test] + fn test_contains_sequence() { + assert_eq!(true, contains_sequence("cc38887a5", '8', 3)); + assert_eq!(true, contains_sequence("cc3eee7a5", 'e', 3)); + + assert_eq!(false, contains_sequence("cc38887a5", 'e', 3)); + assert_eq!(false, contains_sequence("cc3eee7a5", '8', 3)); + } + + #[test] + fn example_01() { + let mut hasher = Hasher::new("abc"); + + let position = hasher.position(|x| find_triplet(&x).is_some()); + + assert_eq!(Some(18), position); + } + + #[test] + fn example_02() { + let hasher = Hasher::new("abc"); + + let position = hasher.skip(19).position(|x| find_triplet(&x).is_some()); + + assert_eq!(Some(39 - 19), position); + } +}