Hash-Identifier
hash-identifier (and its faster CLI cousin hashid) takes an unknown hash and tells you which algorithms could have produced it: it reads the length, character set, and structure, then prints a ranked list of candidates like MD5, SHA-1, NTLM, bcrypt, or sha512crypt. It does not crack anything; it turns “I found a hash, what is it?” into the correct cracking mode so you stop guessing. Reach for it the moment a dumped credential, a config value, or a forensic artifact hands you a string you cannot name.
Mental model: hashid -m 'HASH' - identify, read the [Hashcat Mode: N], hand that number to hashcat. Everything else is one flag away.
New to hashes? Core concepts
- Hash / digest: a fixed-length fingerprint of some input, for example
5f4dcc3b5aa765d61d8327deb882cf99is a 32-char hex MD5 - Length: the biggest clue;
32,40,64,128hex chars each map to a small set of algorithms - Character set: hex-only, base64-ish (
+/=), or printable-with-markers narrows the field before length does - Prefix / tag:
$1$,$5$,$6$,$2y$,$y$,{SSHA}announce the type outright; read them and skip the guess - Salt: random bytes folded in so equal passwords hash differently, usually stored inline as
$id$salt$digest - Hashcat mode / JtR format: the real output you want, for example
-m 0/--format=raw-md5for MD5,-m 1000/ntfor NTLM - Length collision: many algorithms share a length (32 hex could be MD5, NTLM, MD4, an LM half), so a match is a candidate, never proof
When to reach for a hash identifier (and when not)
Reach for it to name an unknown hash from a CTF dump, a config file, or a forensic artifact, to triage a mixed pile before cracking, or to get the right hashcat -m or john --format fast without memorizing every format.
Reach for something else when the source already names the format (a /etc/shadow line is crypt, an NTDS dump is NTLM, a .htpasswd line tells you by its prefix), when the string carries an unambiguous $prefix$ (just read it), or when you need the whole salted hash:salt structure to crack (identifying the bare digest will not give you a working mode). The actual cracking is hashcat or john, never this tool.
Install, update, verify#
sudo apt update && sudo apt install -y hash-identifier hashid # Debian / Ubuntu / Kali
pipx install name-that-hash # nth: richer identifier (optional)
pipx install hashid # isolated install off Kali
sudo apt install --only-upgrade -y hash-identifier hashid # update
command -v hashid hash-identifier # confirm both are on PATH
hashid --version # confirm the version
hashid '5f4dcc3b5aa765d61d8327deb882cf99' # self-test: candidate list should lead with MD5
hashid reads a hash as a positional argument (or one per line from a file or STDIN); hash-identifier is interactive only and prompts for HASH:. The classic tool may also be invoked as hash-id.py depending on how it was installed.
Flags you’ll actually use#
These are hashid, the scriptable workhorse (the classic hash-identifier takes no flags, it just prompts). Skim these first; the cheat sheet below is these flags combined.
| Flag | Does | Flag | Does |
|---|---|---|---|
-m | hashid: add hashcat mode [Hashcat Mode: N] | nth -t | name-that-hash: identify one string |
-j | hashid: add john format [JtR Format: name] | nth -f | nth: identify a file, one hash per line |
-e | hashid: include rare / salted matches | nth -g | nth: greppable JSON output for scripts |
-o FILE | hashid: write results to a file | nth -a | nth: accessible output (no ASCII art) |
FILE | hashid: positional file = one hash per line | nth -e | nth: extract a hash from surrounding junk |
- / STDIN | hashid: pipe hashes in (cat f | hashid -m) | nth -b64 | nth: base64-decode before identifying |
Cheat sheet#
Every block starts simple and adds one flag at a time, so you can stop at the line that does the job.
# Build up an identify: stop at the line you need
hashid 'HASH' # 1. ranked candidate list (length + charset)
hashid -m 'HASH' # 2. + hashcat mode: [Hashcat Mode: 0]
hashid -j 'HASH' # 3. + john format: [JtR Format: raw-md5]
hashid -mj 'HASH' # 4. + both at once (what you usually want)
hashid -mje 'HASH' # 5. + rare / salted formats too (when 1-4 miss)
# Triage many hashes
hashid -m hashes/dump.txt # a file: one candidate block per line
cat hashes/dump.txt | hashid -m # or pipe them in on STDIN
hashid -mj hashes/dump.txt -o notes/ids.txt # save the ids + modes to notes
# Clean the input first (the usual cause of a bad guess)
tr -d '[:space:]' < hashes/raw.txt > hashes/clean.txt # strip stray whitespace / newlines
cut -d: -f2 hashes/creds.txt > hashes/only.txt # drop the user: field, keep the digest
# name-that-hash: richer output, summaries, links
nth -t 'HASH' # one hash, with hashcat + john lines filled in
nth -f hashes/dump.txt # a whole file
nth -g -t 'HASH' | jq . # JSON out, pipe into a script
nth -a -t 'HASH' # plain text, no ASCII art (screen readers / logs)
# Classic interactive tool (no flags, it prompts you)
hash-identifier # paste each hash at the HASH: prompt; blank line to exit
# Read a prefix and skip the tool entirely (verify, do not assume)
# $1$... md5crypt hashcat -m 500 john --format=md5crypt
# $5$... sha256crypt hashcat -m 7400 john --format=sha256crypt
# $6$... sha512crypt hashcat -m 1800 john --format=sha512crypt
# $2a/b/y$ bcrypt hashcat -m 3200 john --format=bcrypt
# $y$... yescrypt modern crypt default; identify by prefix, crack with john
# {SSHA} salted SHA-1 hashcat -m 111 (Netscape / LDAP SSHA)
# Length cues for bare hex (a candidate, never proof)
# 32 hex MD5 / NTLM / MD4 hashcat -m 0 / 1000 / 900
# 40 hex SHA-1 hashcat -m 100
# 64 hex SHA-256 hashcat -m 1400
# 128 hex SHA-512 hashcat -m 1700
Command breakdowns#
Each block below explains one situation, the exact command, and what to expect back.
Identify a single unknown hash#
hashid '5f4dcc3b5aa765d61d8327deb882cf99'
Prints [+] MD5, [+] NTLM, [+] MD4, and other 32-hex candidates, most likely first. The list is driven by length and character set, so treat every line as a candidate to confirm, not a fact.
Get the hashcat mode to crack with#
hashid -m '5f4dcc3b5aa765d61d8327deb882cf99'
Annotates each candidate as [+] MD5 [Hashcat Mode: 0], [+] NTLM [Hashcat Mode: 1000]. That number goes straight into hashcat -m 0. This is the flag you will use nine times out of ten.
Get the John the Ripper format name#
hashid -j '5f4dcc3b5aa765d61d8327deb882cf99'
Adds [JtR Format: raw-md5], the string john wants after --format=. Combine both with hashid -mj 'HASH' when you have not decided which cracker to use.
Identify a SHA-1 hash#
hashid -m 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'
Forty hex chars: the top candidate is SHA-1, [Hashcat Mode: 100]. RIPEMD-160 and a few others share the length, so confirm against the source if the crack will cost real time.
Read a crypt-style shadow hash by its prefix#
hashid -m '$6$abc123$Zr...trimmed...0/'
The $6$ prefix is decisive: sha512crypt, [Hashcat Mode: 1800]. $1$ is md5crypt (500), $5$ is sha256crypt (7400). These come from /etc/shadow, and the prefix beats any length heuristic.
Recognize a bcrypt hash and its cost#
hashid -m '$2y$10$abcdefghijklmnopqrstuv...trimmed'
$2a$ / $2b$ / $2y$ is bcrypt, [Hashcat Mode: 3200]. The 10 right after is the cost factor: each step doubles the work, so a high cost means a small, targeted wordlist and realistic expectations.
Triage a whole file of mixed hashes#
hashid -m hashes/dump.txt
Pass the file as the positional argument (there is no -f flag) and hashid analyzes one hash per line, printing an Analyzing '...' header and candidates for each. Sort the output into per-type files so each cracking run uses one consistent mode.
Pipe hashes in from another command#
cut -d: -f2 creds.txt | hashid -m
With no argument hashid reads STDIN, so you can strip the user: field with cut and identify only the digests in one pass. Handy when the dump is user:hash per line.
Save the identifications to your notes#
hashid -mj hashes/dump.txt -o notes/hash-ids.txt
-o writes the full annotated list to a file instead of the terminal, keeping a clean record of what each hash probably is with both crack-mode hints. Re-runnable and greppable later.
Widen the search to rare or salted formats#
hashid -e 'somethingunusuallooking=='
Without -e, hashid hides less-likely and salted-password matches to keep the list short. Add it when the common guesses miss, for odd application-specific or base64-wrapped hashes.
Identify with name-that-hash for summaries and links#
nth -t '5f4dcc3b5aa765d61d8327deb882cf99'
nth prints the same candidates with a one-line description, a “least likely” section, and hashcat/john lines already filled in. Better ranking on some odd formats, at the cost of a separate install.
Get machine-readable output for a script#
nth -g -t '5f4dcc3b5aa765d61d8327deb882cf99' | jq .
-g emits JSON instead of the banner UI, so a script can parse the candidate names and modes and branch on them. Use -a instead when you want plain text without the ASCII art (screen readers, log files).
Extract a hash buried in other text#
nth -e -t '####5f4dcc3b5aa765d61d8327deb882cf99####'
nth’s -e (extreme) finds the hash inside surrounding junk instead of failing on the whole string, so you can paste a log line or a config fragment and still get an identification. Note that hashid’s -e means something different (extended matches).
Inspect hashes one at a time interactively#
hash-identifier
The classic tool takes no arguments: it prompts HASH:, you paste one string, it prints length-based candidates, and it loops for the next. A blank line or Ctrl-C exits. Fine for a quick manual look, but no mode hints.
Reading the output#
[+] MD5 [Hashcat Mode: 0][JtR Format: raw-md5]- one candidate; the bracketed values are exactly whathashcat -mandjohn --format=want.- The first line is the most likely, not the only one. Read the whole block; length collisions put several real options together.
[+] Unknown hashmeans nothing matched: the input is truncated, base64-wrapped (tryhashid -eornth -b64), or carries stray whitespace.Analyzing '...'headers appear when you pass a file or STDIN, one per input line, so you can tell which candidates belong to which hash.- A
$prefix$in the string overrides the ranking: trust$6$,$2y$, or{SSHA}over any length-based guess listed near it.
Troubleshooting#
| Problem | Cause | Fix |
|---|---|---|
command not found | Not installed / stale PATH | Reinstall; open a fresh shell |
[+] Unknown hash | Truncated, wrapped, or salted input | Add -e; try nth -b64; check the source format |
| Identified the username | Passed the whole user:hash line | cut -d: -f2 first, keep only the digest |
| Length looks off by one or two | Trailing newline or space | tr -d '[:space:]' before identifying |
-f throws an error | hashid has no -f flag | Pass the file as a positional arg, or pipe on STDIN |
| Wrong crack mode chosen | Length collision (MD5 vs NTLM) | Use context; test both -m 0 and -m 1000 on one sample |
| Candidates differ from a guide | Version / format-DB changes | Check hashid --version; cross-check with nth |
Gotchas#
-mprints the hashcat number, not proof of the algorithm. A 32-hex string is MD5 and NTLM and MD4; where you found it breaks the tie, not the tool.- NTLM and MD5 are byte-for-byte indistinguishable (both 32 hex). If a
raw-md5crack stalls on a Windows dump, it is almost certainly NTLM (-m 1000). - A
user:hashline silently identifies the wrong field. hashid analyzes the whole string, so the username changes the length and poisons the guess; strip to the digest first. - hashid takes files as a positional argument, not
-f.hashid -f fileerrors, whilehashid fileorcat file | hashidworks. The-fflag belongs tonth. - A trailing newline changes the apparent length. Pasting from a browser or
echowithout-nadds a byte, and 33 “hex” chars matches nothing;tr -d '[:space:]'fixes it.
Pairs with#
hashcat cracks on the GPU with the -m number this prints; john cracks on the CPU with the --format= name from -j. Point either at a wordlist from seclists. When you would rather attack the live login than the offline hash, reach for hydra. name-that-hash is the friendlier identifier when you want summaries and links, and the classic hash-identifier is fine for a one-off manual look, but hashid stays the most scriptable; once you learn the common length-to-type map you will name most hashes by eye and only reach for a tool on the odd ones.