Skip to content

Commit a574032

Browse files
Add core functionality for password hashing and cracking utilities
- Implemented Argon2id, bcrypt, and scrypt hashing algorithms with verification. - Created a unified CLI for hashing and attack demos. - Developed rainbow table functionality for MD5 hashes. - Added dictionary attack logic for password verification. - Introduced modules for managing hash records and wordlists. - Included tests for hashing, rainbow table operations, and record management. - Added example usage and documentation in README.md. - Established project structure with pyproject.toml and requirements files.
1 parent 8892ba8 commit a574032

42 files changed

Lines changed: 2708 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 4
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
indent_size = 2
13+
trim_trailing_whitespace = false

.github/workflows/python-ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: python-ci
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
python-version: ["3.10", "3.11", "3.12"]
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
23+
- name: Install dependencies
24+
run: |
25+
python -m pip install --upgrade pip
26+
pip install -e .[dev]
27+
28+
- name: Lint
29+
run: ruff check .
30+
31+
- name: Test
32+
run: pytest

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.venv/
2+
__pycache__/
3+
*.pyc
4+
.pytest_cache/
5+
.ruff_cache/
6+
.mypy_cache/
7+
.coverage
8+
dist/
9+
build/
10+
hash_password_cracker/tempCodeRunnerFile.py
11+
tempCodeRunnerFile.py
12+
hash_records.json
13+
hash_records*.json

CONTRIBUTING.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Contributing Guide
2+
3+
Thanks for your interest in improving this project. This repository is intentionally simple and educational, so clarity matters more than cleverness.
4+
5+
## Quick start
6+
7+
1. Create a virtual environment and install dev dependencies:
8+
9+
```bash
10+
python -m venv .venv
11+
.venv\Scripts\Activate.ps1
12+
pip install -r requirements-dev.txt
13+
```
14+
15+
2. Run tests and lint:
16+
17+
```bash
18+
pytest
19+
ruff check .
20+
```
21+
22+
## Coding principles
23+
24+
- Prefer clear, readable code over clever optimizations.
25+
- Keep the educational intent intact: explain why, not just how.
26+
- Avoid changing defaults unless you also update docs and tests.
27+
28+
## Adding new features
29+
30+
If you add a new feature:
31+
32+
- Add tests in `tests/`
33+
- Update `README.md` and any relevant script docs
34+
- Keep CLI behavior backward compatible where possible
35+
36+
## Reporting issues
37+
38+
If you find a bug or unclear behavior, open an issue with:
39+
40+
- The script or function name
41+
- The exact input used
42+
- The observed output
43+
- The expected output
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""Educational demo: build a tiny rainbow table from a small dictionary.
2+
3+
This demonstrates why unsalted, fast hashes (like MD5) are dangerous.
4+
"""
5+
6+
from __future__ import annotations
7+
8+
import hashlib
9+
from typing import Iterable
10+
11+
12+
def build_rainbow_table(words: Iterable[str]) -> dict[str, str]:
13+
"""Return a mapping of md5_hash -> plaintext."""
14+
table: dict[str, str] = {}
15+
for word in words:
16+
md5_hash = hashlib.md5(word.encode("utf-8")).hexdigest()
17+
table[md5_hash] = word
18+
return table
19+
20+
21+
def main() -> None:
22+
dictionary = ["123456", "password", "qwerty", "letmein", "admin"]
23+
24+
print("Building rainbow table from a tiny dictionary...")
25+
table = build_rainbow_table(dictionary)
26+
27+
print("\nRainbow table entries (md5 -> plaintext):")
28+
for md5_hash, word in table.items():
29+
print(f"{md5_hash} : {word}")
30+
31+
stolen_password = "qwerty"
32+
stolen_hash = hashlib.md5(stolen_password.encode("utf-8")).hexdigest()
33+
34+
print("\nSimulated stolen hash:")
35+
print(stolen_hash)
36+
37+
recovered = table.get(stolen_hash)
38+
if recovered:
39+
print(f"\nPassword cracked! Plaintext is: {recovered}")
40+
else:
41+
print("\nPassword not found in the rainbow table.")
42+
43+
print("\nKey lesson: MD5 is fast and unsalted, so rainbow tables can crack it quickly.")
44+
45+
46+
if __name__ == "__main__":
47+
main()
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Educational demo: salted vs unsalted hashes.
2+
3+
This is not a password storage recommendation. It only shows why salts matter.
4+
"""
5+
6+
from __future__ import annotations
7+
8+
import hashlib
9+
import os
10+
11+
12+
def sha256_hex(data: bytes) -> str:
13+
return hashlib.sha256(data).hexdigest()
14+
15+
16+
def main() -> None:
17+
password = "password123"
18+
19+
unsalted_1 = sha256_hex(password.encode("utf-8"))
20+
unsalted_2 = sha256_hex(password.encode("utf-8"))
21+
22+
salt_a = os.urandom(16)
23+
salt_b = os.urandom(16)
24+
25+
salted_1 = sha256_hex(salt_a + password.encode("utf-8"))
26+
salted_2 = sha256_hex(salt_b + password.encode("utf-8"))
27+
28+
print("Password:", password)
29+
print("\nUnsalted hash 1:")
30+
print(unsalted_1)
31+
print("Unsalted hash 2:")
32+
print(unsalted_2)
33+
34+
print("\nSalted hash 1 (salt A):")
35+
print(salted_1)
36+
print("Salted hash 2 (salt B):")
37+
print(salted_2)
38+
39+
print("\nKey lesson: salting makes identical passwords hash differently.")
40+
41+
42+
if __name__ == "__main__":
43+
main()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Educational demo: why rainbow tables fail against Argon2id.
2+
3+
Argon2id uses a random salt, so the same password produces different hashes.
4+
"""
5+
6+
from __future__ import annotations
7+
8+
from argon2 import PasswordHasher
9+
10+
11+
def main() -> None:
12+
ph = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=4)
13+
14+
password = "password123"
15+
hash1 = ph.hash(password)
16+
hash2 = ph.hash(password)
17+
18+
print("Password:", password)
19+
print("\nHash 1:")
20+
print(hash1)
21+
print("\nHash 2:")
22+
print(hash2)
23+
24+
print("\nEven though the password is the same, the hashes are different.")
25+
print("That's the salt doing its job, which breaks rainbow tables.")
26+
27+
28+
if __name__ == "__main__":
29+
main()

DeepDriveForLearners/readme.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# DeepDriveForLearners
2+
3+
This folder contains small, focused learning scripts. Each file is short on purpose so you can read it in a few minutes and understand the concept.
4+
5+
## Scripts
6+
7+
- `DictionaryToBuildaRainbowTable.py`: Builds a tiny rainbow table from a small dictionary and cracks a simulated MD5 hash.
8+
- `WhyRainbowTablesFailwithArgon2id.py`: Shows that the same password produces different Argon2id hashes because of random salt.
9+
- `SaltedVsUnsaltedDemo.py`: Demonstrates how salting changes hashes even when the password is the same.
10+
11+
## How to run
12+
13+
From the project root:
14+
15+
```bash
16+
python DeepDriveForLearners\DictionaryToBuildaRainbowTable.py
17+
python DeepDriveForLearners\WhyRainbowTablesFailwithArgon2id.py
18+
python DeepDriveForLearners\SaltedVsUnsaltedDemo.py
19+
```
20+
21+
## Learning goal
22+
23+
These are conceptual demos, not production patterns. They exist to help you internalize why modern password hashing uses salt and cost factors.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Hash Password Cracker Contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)