Hash Type Identifier — PHP source
Identify the likely hash algorithm of a hash string by its length and character set - MD5, SHA-1/2/3, BLAKE, CRC32, NTLM, bcrypt, Argon2 and more.
This is the PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.
<?php
/*
* Hash-type identifier — PHP port.
*
* Language: PHP
* CosmoDev polyglot showcase port of the `hash-type-identifier` tool.
* Ported from src/lib/hashIdentify.ts.
*
* Display source — part of CosmoDev's polyglot tool pages
* (dev.cosmolabs.org).
*
* Pure string classification: inspect a candidate hash's charset and length
* to suggest likely algorithms. No hashing happens here — this is pattern
* recognition over an already-computed digest. Deterministic; never throws.
*/
declare(strict_types=1);
namespace CosmoDev\HashIdentifier;
/**
* Hex candidates keyed by hex-string length. Each hex char encodes 4 bits,
* so a 64-char hex digest implies a 256-bit algorithm such as SHA-256.
*/
const HEX_BY_LENGTH = [
8 => ['CRC32', 'Adler-32'],
16 => ['MySQL 3.x', 'CRC64'],
32 => ['MD5', 'MD4', 'NTLM', 'LM', 'MD2', 'RIPEMD-128', 'HAVAL-128'],
40 => ['SHA-1', 'RIPEMD-160', 'HAVAL-160', 'MySQL 5.x (SHA1(SHA1))', 'Tiger-160'],
56 => ['SHA-224', 'SHA3-224', 'BLAKE2s-224', 'HAVAL-224'],
64 => ['SHA-256', 'SHA3-256', 'BLAKE2s-256', 'RIPEMD-256', 'Skein-256'],
96 => ['SHA-384', 'SHA3-384', 'BLAKE2b-384'],
128 => ['SHA-512', 'SHA3-512', 'BLAKE2b-512', 'Whirlpool', 'Skein-512'],
];
/**
* Base64 candidates keyed by encoded-string length (16-byte MD5 digest ->
* 24 base64 chars including padding, etc.).
*/
const BASE64_BY_LENGTH = [
24 => ['MD5 (base64)'],
28 => ['SHA-1 (base64)'],
44 => ['SHA-256 (base64)'],
88 => ['SHA-512 (base64)'],
];
/**
* Classify the charset of a candidate hash string.
*
* bcrypt and argon2 use their `$...$` modular-crypt format, so they are
* matched by prefix (the trailing payload is variable); the patterns carry
* no end anchor. hex and base64 match the *entire* string, and hex is
* checked first because any hex digest is also a legal base64 character set.
*
* @param string $s
* @return string one of 'hex', 'base64', 'bcrypt', 'argon2', 'unknown'
*/
function detect_charset(string $s): string
{
if (preg_match('/^\$2[abxy]?\$/', $s) === 1) {
return 'bcrypt';
}
if (preg_match('/^\$argon2(id|i|d)?\$/', $s) === 1) {
return 'argon2';
}
if (preg_match('/^[0-9a-fA-F]+$/', $s) === 1) {
return 'hex';
}
// `+` inside the class is literal; the escaped `\/` keeps the PCRE
// delimiter unambiguous. Standard base64 alphabet, 0–2 padding chars.
if (preg_match('/^[A-Za-z0-9+\/]+={0,2}$/', $s) === 1) {
return 'base64';
}
return 'unknown';
}
/**
* Identify candidate hash types for an input string.
*
* Always returns an info array; never throws. An empty, unrecognised, or
* wrong-length input simply yields an empty `candidates` list — the caller
* decides whether "no candidates" means "not a hash".
*
* @param string $input
* @return array{input: string, cleaned: string, length: int, charset: string, candidates: array<array{name: string, bitLength: int}>}
*/
function identify_hash(string $input): array
{
$cleaned = trim($input);
$charset = detect_charset($cleaned);
$length = strlen($cleaned);
$candidates = [];
switch ($charset) {
case 'bcrypt':
// bcrypt's modular-crypt token encodes a 184-bit effective hash.
$candidates[] = ['name' => 'bcrypt', 'bitLength' => 184];
break;
case 'argon2':
// Argon2 output length is parameter-driven, so no fixed bit length applies.
$candidates[] = ['name' => 'Argon2', 'bitLength' => 0];
break;
case 'hex':
// length*4 converts hex-char count to a bit width (4 bits per nibble).
foreach (HEX_BY_LENGTH[$length] ?? [] as $name) {
$candidates[] = ['name' => $name, 'bitLength' => $length * 4];
}
break;
case 'base64':
// Each base64 char carries 6 bits; round to the nearest byte boundary
// so the reported length lines up with the underlying digest width.
$bitLength = (int) round($length * 6 / 8) * 8;
foreach (BASE64_BY_LENGTH[$length] ?? [] as $name) {
$candidates[] = ['name' => $name, 'bitLength' => $bitLength];
}
break;
}
return [
'input' => $input,
'cleaned' => $cleaned,
'length' => $length,
'charset' => $charset,
'candidates' => $candidates,
];
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →