hash-identifier is a command-line utility tool that automatically identifies the type and algorithm of cryptographic hash values. By analyzing hash format, length, and patterns, hash-identifier determines which hashing algorithm was used, enabling informed selection of cracking tools and techniques. The tool supports hundreds of hash types including MD5, SHA family, bcrypt, NTLM, LM, MySQL, Oracle, and many others.
Hash-identifier is essential for penetration testers, password security researchers, and forensic analysts who need to quickly identify unknown hash types during security assessments, password cracking operations, and digital forensics investigations.
# Install from apt (Debian/Ubuntu/Kali)
sudo apt-get update
sudo apt-get install hash-identifier
# Or download from GitHub
git clone https://github.com/blackploit/hash-identifier.git
cd hash-identifier
chmod +x hash-identifier.py
# Verify installation
hash-identifier --version
# or
python3 hash-identifier.py --version
# Using Homebrew
brew install hash-identifier
# Or from source
git clone https://github.com/blackploit/hash-identifier.git
cd hash-identifier
chmod +x hash-identifier.py
sudo cp hash-identifier.py /usr/local/bin/hash-identifier
# Clone repository
git clone https://github.com/blackploit/hash-identifier.git
# Make executable
chmod +x hash-identifier.py
# Create symbolic link
sudo ln -s /path/to/hash-identifier.py /usr/local/bin/hash-identifier
# Or run directly
python3 hash-identifier.py
# Launch interactive mode
hash-identifier
# At prompt, enter hash:
# Please enter the hash string or 'quit' to exit:
# e99a18c428cb38d5f260853678922e03
# Tool analyzes and displays likely hash types
# Identify specific hash
hash-identifier -hash "e99a18c428cb38d5f260853678922e03"
# Quick identification
echo "e99a18c428cb38d5f260853678922e03" | hash-identifier
# From file
hash-identifier -hash "$(cat hash.txt)"
# Typical output format:
# Possible Hashs:
# [+] MD5
# [+] MD5(WordPress)
# [+] MD5(Joomla)
# [+] HAVAL-128
# [+] Tiger-128
# [+] Skein-256(?)
| Length | Hex Chars | Likely Hash Type | Example |
|---|
| 32 | 32 | MD5, MD4, NTLM | 5d41402abc4b2a76b9719d911017c592 |
| 40 | 40 | SHA-1 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d |
| 56 | 56 | SHA-224, MySQL323 | 90dff4fb4f49a2c2cb8e8506156b5cf29a335d6987521e21 |
| 64 | 64 | SHA-256, RIPEMD-256 | 2c26b46911185131006cba356cb9e8e5bb557135f7601e8e36521f409b692d |
| 96 | 96 | SHA-384 | 3391fdddfc8dc7393707a6b0cdc13ee345ab8f1a9caa28e5fa3b5fc2e12e7346c8f83adae11f0f7bcde0f7f4d45ad4ce |
| 128 | 128 | SHA-512, Whirlpool | f8daf8f8a01a33a8d35a4ff4cd7f0f12f0b7a3e9e4d1c5b4c9e8d1f2a3b4c5d |
# MD5 Hash (32 hex characters)
hash-identifier -hash "5d41402abc4b2a76b9719d911017c592"
# SHA-1 Hash (40 hex characters)
hash-identifier -hash "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"
# SHA-256 Hash (64 hex characters)
hash-identifier -hash "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
# bcrypt Hash (60 characters, starts with $2)
hash-identifier -hash '$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW'
# MD5 crypt (34 characters, starts with $1$)
hash-identifier -hash '$1$jMtuHIKA$t5TqUXDwfMNlRx8Wc9b1L1'
# Create file with hashes (one per line)
cat > hashes.txt << 'EOF'
e99a18c428cb38d5f260853678922e03
f5a5a608146ce0e40b2e9187f8a4ce38
356a192b7913b04c54574d18c28d46e6395428ab
EOF
# Identify all hashes
for hash in $(cat hashes.txt); do
echo "Hash: $hash"
hash-identifier -hash "$hash"
echo ""
done
| Hash Type | Typical Length | Used By | Format |
|---|
| MD5 | 32 | Outdated systems, WordPress | 5d414… |
| SHA-1 | 40 | Git, SVN, legacy systems | aaf4c6… |
| SHA-256 | 64 | Modern systems, Linux | e3b0c4… |
| bcrypt | 60 | Modern password storage | $2a$12$… |
| SHA-512 | 128 | Linux shadow files | f8daf8… |
| PBKDF2 | Variable | OWASP recommended | varies |
| Argon2 | Variable | New standard | $argon2… |
| Scrypt | Variable | Modern applications | varies |
| Database | Common Algorithm | Identification |
|---|
| MySQL 3.23 | MySQL323 | 16 hex characters |
| MySQL 4.1+ | MySQL5 | 41 character string |
| MSSQL 2000 | MSSQL | 0x… prefix |
| Oracle | Oracle | 16 hex characters |
| PostgreSQL | MD5/SHA | variable |
| MongoDB | SCRAM-SHA-1 | complex format |
# 1. Launch interactive mode
hash-identifier
# 2. Receive prompt
# _______________________________________________________________
# HASH IDENTIFIER v1.3
# _______________________________________________________________
# Please enter the hash string or 'quit' to exit:
# 3. Enter hash
e99a18c428cb38d5f260853678922e03
# 4. Review results
# Possible Hashs:
# [+] MD5
# [+] MD5(WordPress)
# [+] MD4
# [+] Double MD5
# [+] LM
# 5. Analyze likelihood based on context
# 6. Select most probable algorithm
# 7. Choose appropriate cracking tool
# Identify by format pattern:
# Hash starts with $2a$ or $2b$ or $2y$ = bcrypt
echo "$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW" | hash-identifier
# Hash starts with $1$ = MD5 crypt
echo "$1$jMtuHIKA$t5TqUXDwfMNlRx8Wc9b1L1" | hash-identifier
# Hash starts with $5$ = SHA-256 crypt
echo "$5$saltvalue$hash..." | hash-identifier
# Hash starts with $6$ = SHA-512 crypt
echo "$6$saltvalue$hash..." | hash-identifier
# Hash starts with $argon2 = Argon2
echo "$argon2i$v=19$m=512,t=2,p=2$..." | hash-identifier
# If hash is from Linux /etc/shadow:
# Likely: bcrypt ($2a$), SHA-256 crypt ($5$), SHA-512 crypt ($6$)
# If hash is from Windows password:
# Likely: NTLM, LM (older systems)
# If hash is from database:
# Likely: MD5, SHA-1, bcrypt, PBKDF2
# If hash is from web application:
# Likely: bcrypt, SHA-256, Argon2, PBKDF2
# If hash is very short (16-20 chars):
# Likely: MySQL, Oracle, or truncated hash
# 1. Obtain hash (from /etc/shadow, database dump, etc.)
sudo cat /etc/shadow | grep username
# 2. Extract hash portion
# username:$6$saltvalue$hashhashhashhash:18000:0:99999:7:::
# 3. Identify hash type
HASH='$6$saltvalue$hashhashhashhash'
hash-identifier -hash "$HASH"
# 4. Select appropriate cracking tool
# SHA-512 crypt identified
# Use: hashcat -m 1800 hash.txt wordlist.txt
# Or: john --format=sha512crypt hash.txt
# 5. Execute crack
hashcat -m 1800 hashes.txt /usr/share/wordlists/rockyou.txt
#!/bin/bash
# analyze_hashes.sh - Process multiple hashes
INPUT_FILE="$1"
OUTPUT_FILE="hash_analysis.txt"
> $OUTPUT_FILE # Clear output file
while IFS= read -r hash; do
echo "======================================" >> $OUTPUT_FILE
echo "Hash: $hash" >> $OUTPUT_FILE
echo "======================================" >> $OUTPUT_FILE
hash-identifier -hash "$hash" >> $OUTPUT_FILE
echo "" >> $OUTPUT_FILE
done < "$INPUT_FILE"
echo "Analysis complete: $OUTPUT_FILE"
# Obtain database dump
sqlite3 database.db ".dump users" > users_dump.sql
# Extract hashes
grep -oE "[a-f0-9]{32}" users_dump.sql > md5_hashes.txt
grep -oE "[a-f0-9]{40}" users_dump.sql > sha1_hashes.txt
# Identify each batch
echo "MD5 Hashes:"
head -1 md5_hashes.txt | xargs hash-identifier -hash
echo "SHA-1 Hashes:"
head -1 sha1_hashes.txt | xargs hash-identifier -hash
# Prepare for cracking
hashcat -m 0 md5_hashes.txt wordlist.txt # MD5
hashcat -m 100 sha1_hashes.txt wordlist.txt # SHA-1
# After identifying hash type, use corresponding hashcat mode
# MD5: mode 0
hash-identifier -hash "5d41402abc4b2a76b9719d911017c592"
hashcat -m 0 hash.txt wordlist.txt
# SHA-1: mode 100
hash-identifier -hash "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"
hashcat -m 100 hash.txt wordlist.txt
# SHA-256: mode 1400
hash-identifier -hash "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
hashcat -m 1400 hash.txt wordlist.txt
# bcrypt: mode 3200
hash-identifier -hash '$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW'
hashcat -m 3200 hash.txt wordlist.txt
# SHA-512 crypt: mode 1800
hash-identifier -hash '$6$saltvalue$hash...'
hashcat -m 1800 hash.txt wordlist.txt
# John the Ripper format mapping
# MD5: raw-md5
hash-identifier -hash "5d41402abc4b2a76b9719d911017c592"
john --format=raw-md5 hash.txt
# SHA-1: raw-sha1
hash-identifier -hash "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"
john --format=raw-sha1 hash.txt
# bcrypt: bcrypt
hash-identifier -hash '$2a$12$...'
john --format=bcrypt hash.txt
# SHA-512 crypt: sha512crypt
hash-identifier -hash '$6$...'
john --format=sha512crypt hash.txt
# MD5 crypt: md5crypt
hash-identifier -hash '$1$...'
john --format=md5crypt hash.txt
# If hash-identifier returns multiple possibilities:
# 1. Consider context (where hash came from)
# 2. Test length validation
length=$(echo -n "hash_string" | wc -c)
echo "Hash length: $length characters"
# 3. Check for format patterns ($2a$, $1$, etc.)
echo "hash_string" | grep -E '^\$[0-9a-z]+\$'
# 4. Try with online hash identifier
# https://cmd5.com/
# https://hashes.com/en/tools/hash_identifier
# 5. If still uncertain, try most likely candidates
# Start with most common: MD5, SHA-1, SHA-256
# Non-hex characters detected
hash-identifier -hash "5d41402abc4b2a76b97-9d911017c592"
# This contains a hyphen - not valid hex
# Correct format:
echo "5d41402abc4b2a76b9719d911017c592" | hash-identifier
# Base64 encoded hash
echo "PW5rVzNxcXIxag==" | hash-identifier
# Extract if embedded in larger string
echo "Hash: 5d41402abc4b2a76b9719d911017c592" | grep -oE "[a-f0-9]{32}" | hash-identifier
#!/usr/bin/env python3
import subprocess
import re
def identify_hash(hash_string):
"""Identify hash type using hash-identifier"""
try:
result = subprocess.run(
['hash-identifier', '-hash', hash_string],
capture_output=True,
text=True
)
output = result.stdout
# Parse output
hashes = []
for line in output.split('\n'):
if line.strip().startswith('[+]'):
hash_type = line.split('[+]')[1].strip()
hashes.append(hash_type)
return hashes
except Exception as e:
return f"Error: {e}"
# Usage
hash_list = [
"5d41402abc4b2a76b9719d911017c592",
"aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d",
"$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW"
]
for h in hash_list:
types = identify_hash(h)
print(f"{h[:20]}... => {types}")
| Situation | Issue | Solution |
|---|
| Similar lengths | Multiple likely types | Use context clues |
| Truncated hash | Shorter than normal | May not identify correctly |
| Salted hash | Different from expected | Look for $salt$ pattern |
| Hashed multiple times | Double MD5, etc. | Identify original algorithm |
| Base64 encoded | Not raw hex | Decode first |
# Double MD5 (hashed twice)
HASH="5d41402abc4b2a76b9719d911017c592"
MD5_OF_MD5=$(echo -n "$HASH" | md5sum | awk '{print $1}')
hash-identifier -hash "$MD5_OF_MD5"
# Salted hash extraction
SALTED_HASH="5d41402abc4b2a76b9719d911017c592:salt123"
HASH_ONLY=$(echo "$SALTED_HASH" | cut -d: -f1)
hash-identifier -hash "$HASH_ONLY"
# Base64 encoded hash
B64_HASH="NWQ0MTQwMmFiYzRiMmE3NmI5NzE5ZDkxMTAxN2M1OTI="
DECODED=$(echo "$B64_HASH" | base64 -d)
hash-identifier -hash "$DECODED"
# Efficient batch processing
time (
while IFS= read -r hash; do
hash-identifier -hash "$hash" -q
done < hashes.txt
) > results.txt
# Count by type
grep "^\[+\]" results.txt | sort | uniq -c | sort -rn
# Extract most likely for each hash
python3 << 'EOF'
import subprocess
import re
with open('hashes.txt', 'r') as f:
for hash_value in f:
hash_value = hash_value.strip()
result = subprocess.run(
['hash-identifier', '-hash', hash_value],
capture_output=True, text=True
)
# Get first match (most likely)
match = re.search(r'\[\+\]\s+(.+)', result.stdout)
if match:
print(f"{hash_value[:20]}... => {match.group(1)}")
EOF
# Online hash lookup
# curl https://hashes.com/api/find?hash=5d41402abc4b2a76b9719d911017c592
# Hashcat built-in identification
hashcat --help | grep "^ -m" | head -20
# John the Ripper format list
john --list=formats | grep -i md5
# CLI combination
echo "Hash: 5d41402abc4b2a76b9719d911017c592" | \
grep -oE "[a-f0-9]{32}" | \
xargs -I {} hash-identifier -hash {}
# Never store hashes in plaintext in scripts
# Use environment variables
export TARGET_HASH="$1"
hash-identifier -hash "$TARGET_HASH"
# Clean sensitive data
unset TARGET_HASH
history -c
# Log safely (without sensitive values)
echo "[$(date)] Hash identification completed" >> audit.log
# Secure temporary files
TMP_HASH=$(mktemp)
echo "$1" > "$TMP_HASH"
hash-identifier -hash "$(cat $TMP_HASH)"
rm -f "$TMP_HASH"
shred -vfz "$TMP_HASH" # Secure deletion
# Verify by creating matching hash
ORIGINAL="password123"
# Create MD5
MD5_HASH=$(echo -n "$ORIGINAL" | md5sum | awk '{print $1}')
hash-identifier -hash "$MD5_HASH"
# Should identify as MD5
# Create SHA-256
SHA256_HASH=$(echo -n "$ORIGINAL" | sha256sum | awk '{print $1}')
hash-identifier -hash "$SHA256_HASH"
# Should identify as SHA-256
# Create bcrypt
BCRYPT_HASH=$(htpasswd -nbBC 10 "" "$ORIGINAL" | grep ':' | cut -d: -f2)
hash-identifier -hash "$BCRYPT_HASH"
# Should identify as bcrypt