Cybersecurity-Projects/PROJECTS/foundations/hash-identifier/learn/00-OVERVIEW.md

159 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Hash Identifier
## What this is
A small Python program that looks at a string of weird-looking characters and tells you what kind of cryptographic hash it probably is. You give it something like this:
```
5f4dcc3b5aa765d61d8327deb882cf99
```
and it tells you "that's an MD5 hash" with a reason for why it thinks so.
That's the whole job. It does not crack the hash. It does not turn the hash back into a password. It just answers the question "what flavor of hash is this?" — which is the question you have to answer *first* before any other tool will help you.
## Why anyone needs this
The first thing that happens when a real attack succeeds is that the attacker walks out with a database dump full of password hashes. The hashes look like nonsense, but they are not random — every hash carries clues about how it was made. Once you know the algorithm (MD5, SHA-256, bcrypt, Argon2, whatever) you can hand the hash to a cracking tool like [hashcat](https://hashcat.net) or [John the Ripper](https://www.openwall.com/john/) and start trying to recover the original password.
But here's the thing: hashcat needs you to tell it the algorithm. It has [over 400 hash modes](https://hashcat.net/wiki/doku.php?id=example_hashes), each with a different number. Mode 0 is MD5. Mode 100 is SHA-1. Mode 3200 is bcrypt. If you pick the wrong mode, hashcat will sit there forever and find nothing. So before cracking, you identify. That's this tool.
**Real-world moments where you'd reach for this:**
- A pentester finds a dump file on a compromised server full of strings like `$2b$12$EixZaYVK1...` and needs to know what to feed hashcat.
- A CTF challenge hands you a hash and zero hints about what algorithm made it.
- You're reading a breach writeup and want to understand whether the leaked passwords were stored as fast unsalted MD5 (a disaster) or slow salted bcrypt (much better).
- The [2012 LinkedIn breach](https://en.wikipedia.org/wiki/2012_LinkedIn_hack) leaked 6.5 million unsalted SHA-1 hashes. The first thing any researcher had to do before doing *anything* was confirm "yes, these are SHA-1." Forty-character hex strings. Easy. The tool you're about to read would have told them that in milliseconds.
## What you will learn
**Security ideas:**
- What a cryptographic hash actually is (a function that turns any input into a fixed-length jumble that you can't reverse).
- The three signals every hash leaks about itself: its **prefix**, its **length**, and its **character set**.
- Why modern password hashes (`$2b$...`, `$argon2id$...`) *announce themselves* on purpose, and why old fast hashes (MD5, SHA-1) don't.
- The difference between a fast hash (made for speed, terrible for passwords) and a slow hash (made on purpose to resist cracking).
- Why you can never recover the password from a hash, only *guess* the password and check if its hash matches.
**Python ideas (assuming this is your first time):**
- How to read a Python file from top to bottom and understand what it's doing.
- What `import` does and where the standard library ends and third-party packages begin.
- Functions, type hints (`str`, `int`, `list[str]`), and what `-> bool` means after a function signature.
- `@dataclass` — a shortcut for making little record-like objects.
- `frozenset`, `dict`, `list`, `tuple` — the core Python containers and when to pick which.
- How a command-line tool actually starts running (the `if __name__ == "__main__"` line at the bottom).
- How a test file works and why every function in the main code has tests next to it.
**Tools you'll touch:**
- [`uv`](https://github.com/astral-sh/uv) — the modern Python package manager. Like `pip` but ~100× faster.
- [`just`](https://github.com/casey/just) — a command runner. Instead of memorizing long commands, you type `just test` or `just run`.
- [`rich`](https://github.com/Textualize/rich) — the library that prints the pretty colored table at the end.
- [`pytest`](https://pytest.org) — Python's test runner.
- [`ruff`](https://github.com/astral-sh/ruff) + [`mypy`](https://mypy-lang.org) + [`pylint`](https://pylint.org) — the linters that yell at you if your code is wrong, slow, or sloppy.
## What you need before starting
**Knowledge you should have:**
- You've used a terminal at least once (you know what `cd` and `ls` do).
- You vaguely know that "a hash" is a one-way function. If not, [01-CONCEPTS.md](./01-CONCEPTS.md) will get you there in 10 minutes.
- You can read code, or at least you're willing to. We will explain every Python feature as we hit it.
**Knowledge you do NOT need:**
- Any prior Python experience. The whole point of the **foundations** tier is that you start here.
- Any prior cybersecurity experience.
- Any math beyond "counting." There is no math in this project. Cryptography uses math under the hood, but identifying a hash by its shape doesn't.
**Software you need installed:**
- Python 3.14 or newer.
- The `uv` tool (the install script will get this for you if you don't have it).
- The `just` tool (also handled by the install script).
- A terminal. Any terminal. On Mac it's Terminal.app or iTerm2; on Linux it's whatever your distro shipped; on Windows it's WSL2 + Ubuntu (we strongly recommend WSL2 instead of native Windows).
You do *not* need an IDE — a text editor is fine. We recommend [VS Code](https://code.visualstudio.com) with the Python extension, but `nano`, `vim`, `helix`, or whatever you already use will work.
## Quick start
From inside `PROJECTS/foundations/hash-identifier/`:
```bash
./install.sh
```
That script will install `uv` and `just` if missing, create a virtual environment (an isolated Python sandbox just for this project), install all the dependencies, and verify the tests pass. It prints what it's doing as it goes — read the output, don't just close the terminal.
Then try the tool:
```bash
just run -- 5f4dcc3b5aa765d61d8327deb882cf99
```
You should see a colored table identifying that string as MD5 (with NTLM, MD4, and RIPEMD-128 as less-likely alternatives — all four produce 32 hex characters, so length alone can't separate them).
Try a few more:
```bash
# bcrypt — modern password hash, announces itself with the $2b$ prefix
just run -- '$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQNQy.uK4Of2T7G'
# SHA-256 — 64 hex characters
just run -- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
# A JWT (this is NOT a hash, but the tool will say so politely)
just run -- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
# Total garbage — the tool will say "no idea" rather than guess
just run -- helloworld
```
**Note on quoting:** when a hash starts with `$`, you must wrap it in single quotes (`'$2b$...'`). Without quotes, your shell will try to expand `$2` as a shell variable and chop the hash up. This is a shell thing, not a Python thing — every Unix shell does it.
## Project layout
```
hash-identifier/
├── hash_identifier.py the whole tool — one file, ~680 lines
├── test_hash_identifier.py tests for every behavior the tool claims to have
├── install.sh one-shot setup script
├── justfile shortcuts for run / test / lint / format
├── pyproject.toml project config: dependencies, linter rules, etc.
├── README.md short pointer to this learn/ folder
├── learn/ you are here
│ ├── 00-OVERVIEW.md quick start (this file)
│ ├── 01-CONCEPTS.md what hashes are and how identification works
│ ├── 02-ARCHITECTURE.md how the code is structured, with diagrams
│ ├── 03-IMPLEMENTATION.md line-by-line walkthrough of the code
│ └── 04-CHALLENGES.md extension ideas if you want to go further
└── assets/ images, screenshots
```
One file of code is on purpose. The foundations tier is meant to be readable in one sitting. The intermediate and advanced tiers split into many files; foundations does not.
## Where to go next
1. **[01-CONCEPTS.md](./01-CONCEPTS.md)** — understand *what* a hash is, *why* identification is the first move, and *how* prefix/length/charset clues actually work. Read this even if you think you know it; the framing matters.
2. **[02-ARCHITECTURE.md](./02-ARCHITECTURE.md)** — see the six-step pipeline the tool uses to make a decision, drawn out as a flow diagram.
3. **[03-IMPLEMENTATION.md](./03-IMPLEMENTATION.md)** — read `hash_identifier.py` with us, line by line. Every Python feature gets explained when it first appears.
4. **[04-CHALLENGES.md](./04-CHALLENGES.md)** — extensions you can try on your own once you've absorbed the rest.
## Common problems
**"command not found: just"**
The install script should set this up, but if it didn't: `curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash`. Then close and reopen your terminal so it sees the new tool.
**"command not found: uv"**
Same idea: `curl -LsSf https://astral.sh/uv/install.sh | sh`, then reopen your terminal.
**`just run -- $2b$12$...` chops the hash up**
You forgot the single quotes around the hash. Re-run with `just run -- '$2b$12$...'`.
**"ModuleNotFoundError: No module named 'rich'"**
You ran `python hash_identifier.py` directly instead of `just run`. The `just run` recipe uses the virtual environment that has `rich` installed. Either use `just run`, or activate the venv first: `source .venv/bin/activate`, *then* `python hash_identifier.py <hash>`.
**Tests fail right after install**
Tests should pass on a fresh `./install.sh`. If they don't, you probably have an older Python (run `python --version`; you need 3.14+). On Ubuntu, install it via [`deadsnakes`](https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa); on Mac use [Homebrew](https://brew.sh).