61 lines
1.7 KiB
Rust
61 lines
1.7 KiB
Rust
use std::{ops::Range, sync::LazyLock, thread};
|
|
|
|
use hex_literal;
|
|
use md2::{Digest, Md2};
|
|
use num_cpus;
|
|
|
|
static MAX_THREADS: LazyLock<usize> = LazyLock::new(|| num_cpus::get());
|
|
|
|
const TARGET: [u8; 16] = hex_literal::hex!("e809236d4b94e54174e666cf3b1f53ce");
|
|
const KNOWN: &str = "CYBERSCI(PUNCH?C4RD?1S?7H3?FL4SH?ST0RAGE?OF?";
|
|
const KNOWN_TRAIL: &str = ")";
|
|
|
|
fn main() {
|
|
let mut handles = vec![];
|
|
|
|
let fraction = u32::MAX as usize / *MAX_THREADS;
|
|
for idx in 0..*MAX_THREADS {
|
|
println!("Spawned worker thread {}", idx);
|
|
handles.push(thread::spawn(move || {
|
|
// Pretend you don't see this.
|
|
// Also, who would have u32::MAX + 1 threads anyway?
|
|
let start = (fraction * idx) as u32;
|
|
brute(start..{ start + fraction as u32 });
|
|
}));
|
|
}
|
|
|
|
for h in handles {
|
|
h.join().unwrap(); // Yes, I'm calling unwrap on Result<_>. No, I don't work at Cloudflare.
|
|
}
|
|
}
|
|
|
|
fn brute(range: Range<u32>) {
|
|
println!("{}..{}", range.start, range.end);
|
|
|
|
// Init MD2 hasher.
|
|
let mut hasher = Md2::new();
|
|
hasher.update(KNOWN);
|
|
let mut result = hasher.finalize_reset();
|
|
|
|
// Brute force given range.
|
|
let mut idx: u32 = range.start;
|
|
let mut guess = String::new();
|
|
while (result[..] != TARGET) && (idx != range.end) {
|
|
idx += 1;
|
|
|
|
let seq: [u8; 4] = idx.clone().to_ne_bytes();
|
|
println!("{:?}", &seq);
|
|
|
|
guess = format!(
|
|
"{}{}{}{}{}{}",
|
|
KNOWN, seq[0] as char, seq[1] as char, seq[2] as char, seq[3] as char, KNOWN_TRAIL
|
|
);
|
|
hasher.update(&guess);
|
|
result = hasher.finalize_reset();
|
|
}
|
|
|
|
if result[..] == TARGET {
|
|
println!("{}", guess);
|
|
}
|
|
}
|