查找QQ号的MD5
网上瞎逛总能碰到点有趣的事情,看到一个名叫谢益辉的博主的自我简介,其中有一段是这样的:
我很少用 QQ,因为即时聊天会打乱时间的完整性,我希望能有整块的时间集中做事情,而不是盯着几个聊天窗口打着零碎的句子。我的 QQ 号的 MD5 码是 ff8fb48d51329ad82a306fa309b97e3a(将 QQ 号写入文件、不带换行符的文件的 MD5 码)。我的主要联系方式是电子邮件。
哈希码的反推只能是硬碰,暴力破拆,好在我们知道QQ号都是数字组成,范围小了很多。我也好奇解出这个号要花多长时间,正好用Rust练习一下。程序非常简单,但里面有几个坑需要提一下。
首先使用的库是md-5,而不是md5,不清楚2个库是怎么回事。
[dependencies]
md-5 = "0.10.6"
程序非常简单,因为不知道计算量多大,我一开始查找范围很小,7位数字,后来范围慢慢扩大。另外,debug运行模式和release模式的效率也是天差地别,需要以release编译和运行:
$ cargo build --release
测试发现7位数字可以在1.2秒左右找完,这个效果比较惊人。那8位大约12秒,9位120秒,10位1200秒(20分钟)。于是我就先找9位数,想如果再找不到,就要用多线程了。好在这个QQ号码只有9位:
peter@~/workspace/md5force $ ./target/release/md5force
Found it: 250145077
Time: 29.146758416s
代码还是比较简单的:
use md5::{Digest, Md5};
use std::time::Instant;
fn find_num_md5(target_hash: &str) -> u64 {
let mut found_number = 0;
let startnum: u64 = 1000;
let endnum: u64 = 999999999;
for num in startnum..=endnum {
let numstr = num.to_string();
let mut hasher = Md5::new();
hasher.update(numstr);
let result = hasher.finalize();
let hash_str = format!("{:x}", result);
if hash_str == target_hash {
found_number = num;
break;
}
}
found_number
}
fn main() {
let start_time = Instant::now();
let target_hash = "ff8fb48d51329ad82a306fa309b97e3a";
let num = find_num_md5(target_hash);
println!("Found it: {num}");
let duration = start_time.elapsed();
println!("Time: {:?}", duration);
}
#[cfg(test)]
mod tests {
use md5::{Digest, Md5};
use crate::find_num_md5;
#[test]
fn test_verify_1() {
let num1 = b"5068775";
let num1_hash = "ee5ccbb2e45d7f5f6af991cb93de6274";
let mut hasher = Md5::new();
hasher.update(num1);
let result = hasher.finalize();
let result_hex = format!("{:x}", result);
assert_eq!(num1_hash, result_hex);
}
#[test]
fn test_find_num_md5() {
let target_hash = "ee5ccbb2e45d7f5f6af991cb93de6274";
let num = find_num_md5(target_hash);
assert_eq!(num, 5068775);
}
#[test]
fn test_find_num_md5_not_found() {
let target_hash = "ee5ccbb2e45d7f5f6af991cb93de6270";
let num = find_num_md5(target_hash);
assert_eq!(num, 0);
}
}