happy_cracking/crypto/
hashid.rs1use anyhow::Result;
2use clap::Subcommand;
3
4#[derive(Subcommand)]
5pub enum HashIdAction {
6 #[command(about = "Identify hash type")]
7 Identify {
8 #[arg(help = "Hash string to identify")]
9 input: String,
10 },
11}
12
13pub fn run(action: HashIdAction) -> Result<()> {
14 match action {
15 HashIdAction::Identify { input } => {
16 let results = identify(&input);
17 if results.is_empty() {
18 println!("Unknown hash format");
19 } else {
20 println!("Possible hash types:");
21 for result in results {
22 println!(" - {}", result);
23 }
24 }
25 }
26 }
27 Ok(())
28}
29
30pub fn identify(input: &str) -> Vec<&'static str> {
31 let input = input.trim();
32 let len = input.len();
33 let is_hex = input.chars().all(|c| c.is_ascii_hexdigit());
34 let is_base64 = input
35 .chars()
36 .all(|c| c.is_ascii_alphanumeric() || c == '+' || c == '/' || c == '=');
37
38 let mut results = Vec::new();
39
40 if is_hex {
41 match len {
42 32 => {
43 results.push("MD5");
44 results.push("MD4");
45 results.push("MD2");
46 results.push("NTLM");
47 }
48 40 => {
49 results.push("SHA-1");
50 results.push("RIPEMD-160");
51 }
52 56 => {
53 results.push("SHA-224");
54 }
55 64 => {
56 results.push("SHA-256");
57 results.push("RIPEMD-256");
58 results.push("Snefru-256");
59 results.push("GOST R 34.11-94");
60 }
61 96 => {
62 results.push("SHA-384");
63 }
64 128 => {
65 results.push("SHA-512");
66 results.push("Whirlpool");
67 results.push("SHA-512/256");
68 }
69 _ => {}
70 }
71 }
72
73 if input.starts_with("$2a$")
75 || input.starts_with("$2b$")
76 || input.starts_with("$2y$")
77 || input.starts_with("$2x$")
78 {
79 results.push("bcrypt");
80 }
81
82 if input.starts_with("$argon2") {
84 results.push("Argon2");
85 }
86
87 if input.starts_with("$1$") {
89 results.push("MD5 Crypt (Unix)");
90 }
91 if input.starts_with("$5$") {
92 results.push("SHA-256 Crypt (Unix)");
93 }
94 if input.starts_with("$6$") {
95 results.push("SHA-512 Crypt (Unix)");
96 }
97
98 if is_base64 && !is_hex {
100 match len {
101 24 => {
102 results.push("MD5 (Base64)");
103 }
104 28 => {
105 results.push("SHA-1 (Base64)");
106 }
107 44 => {
108 results.push("SHA-256 (Base64)");
109 }
110 88 => {
111 results.push("SHA-512 (Base64)");
112 }
113 _ => {}
114 }
115 }
116
117 if len == 16 && is_hex {
119 results.push("MySQL (old)");
120 }
121 if len == 41 && input.starts_with('*') {
122 results.push("MySQL 5.x");
123 }
124
125 results
126}