2016/14
This commit is contained in:
137
2016/14/src/main.rs
Normal file
137
2016/14/src/main.rs
Normal file
@@ -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<String> {
|
||||
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<char> {
|
||||
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::<String>())
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user