Skip to content

Commit 81233e3

Browse files
author
Saiprashanth Pulisetti
committed
feat(cyber_security): add hash_cracker CLI
1 parent 78a6a2d commit 81233e3

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

cyber_security/hash_cracker.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python3
2+
"""Hash cracker for md5/sha1/sha256 using a wordlist.
3+
4+
Usage:
5+
python -m cyber_security.hash_cracker --algo sha256 --hash <hash> --wordlist words.txt
6+
"""
7+
from __future__ import annotations
8+
9+
import argparse
10+
import hashlib
11+
import sys
12+
from typing import Iterable
13+
14+
15+
ALGORITHMS = {"md5", "sha1", "sha256"}
16+
17+
18+
def iter_wordlist(path: str) -> Iterable[str]:
19+
with open(path, "r", encoding="utf-8", errors="ignore") as f:
20+
for line in f:
21+
word = line.rstrip("\n\r")
22+
if word:
23+
yield word
24+
25+
26+
def crack_hash(target_hash: str, algo: str, wordlist_path: str) -> str | None:
27+
algo = algo.lower()
28+
if algo not in ALGORITHMS:
29+
raise ValueError(f"Unsupported algorithm: {algo}")
30+
31+
target_hash = target_hash.lower()
32+
for candidate in iter_wordlist(wordlist_path):
33+
h = hashlib.new(algo)
34+
h.update(candidate.encode("utf-8"))
35+
if h.hexdigest().lower() == target_hash:
36+
return candidate
37+
return None
38+
39+
40+
def parse_args(argv: list[str]) -> argparse.Namespace:
41+
parser = argparse.ArgumentParser(description="Hash cracker using a wordlist.")
42+
parser.add_argument("--algo", choices=sorted(ALGORITHMS), default="sha256", help="Hash algorithm")
43+
parser.add_argument("--hash", required=True, help="Target hex digest")
44+
parser.add_argument("--wordlist", required=True, help="Path to wordlist file")
45+
parser.add_argument("--quiet", action="store_true", help="Only print the cracked password if found")
46+
return parser.parse_args(argv)
47+
48+
49+
def main(argv: list[str] | None = None) -> int:
50+
args = parse_args(sys.argv[1:] if argv is None else argv)
51+
try:
52+
result = crack_hash(args.hash, args.algo, args.wordlist)
53+
except FileNotFoundError:
54+
print(f"Wordlist not found: {args.wordlist}", file=sys.stderr)
55+
return 2
56+
except ValueError as exc:
57+
print(str(exc), file=sys.stderr)
58+
return 2
59+
60+
if result is None:
61+
if not args.quiet:
62+
print("No match found.")
63+
return 1
64+
65+
print(result)
66+
return 0
67+
68+
69+
if __name__ == "__main__": # pragma: no cover
70+
raise SystemExit(main())

0 commit comments

Comments
 (0)