Skip to content

Hash Type Identifier — TypeScript 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 TypeScript implementation — the same logic the interactive tool runs, in a shareable, citable form.

// Pure hash-type identification - no React, no DOM, deterministic.
// Classifies a string's charset and suggests likely hash algorithms by
// length. Never throws.

export interface HashMatch {
  name: string;
  bitLength: number; // hex length * 4, where applicable
}

export type HashCharset = 'hex' | 'base64' | 'bcrypt' | 'argon2' | 'unknown';

export interface HashInfo {
  input: string;
  cleaned: string; // trimmed
  length: number;
  charset: HashCharset;
  candidates: HashMatch[];
}

// Hex candidates keyed by hex-string length.
const HEX_BY_LENGTH: Record<number, string[]> = {
  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 length (decoded-byte length × 4/3 rounded).
const BASE64_BY_LENGTH: Record<number, string[]> = {
  24: ['MD5 (base64)'],
  28: ['SHA-1 (base64)'],
  44: ['SHA-256 (base64)'],
  88: ['SHA-512 (base64)'],
};

export function detectCharset(s: string): HashCharset {
  if (/^\$2[abxy]?\$/.test(s)) return 'bcrypt';
  if (/^\$argon2(id|i|d)?\$/.test(s)) return 'argon2';
  if (/^[0-9a-fA-F]+$/.test(s)) return 'hex';
  if (/^[A-Za-z0-9+/]+={0,2}$/.test(s)) return 'base64';
  return 'unknown';
}

/** Identify candidate hash types. Always returns HashInfo; never throws. */
export function identifyHash(input: string): HashInfo {
  const cleaned = (input || '').trim();
  const charset = detectCharset(cleaned);
  const length = cleaned.length;
  let candidates: HashMatch[] = [];

  if (charset === 'bcrypt') {
    candidates = [{ name: 'bcrypt', bitLength: 184 }];
  } else if (charset === 'argon2') {
    candidates = [{ name: 'Argon2', bitLength: 0 }];
  } else if (charset === 'hex') {
    const names = HEX_BY_LENGTH[length] ?? [];
    candidates = names.map((name) => ({ name, bitLength: length * 4 }));
  } else if (charset === 'base64') {
    const names = BASE64_BY_LENGTH[length] ?? [];
    candidates = names.map((name) => ({ name, bitLength: Math.round((length * 6) / 8) * 8 }));
  }

  return { input: input ?? '', cleaned, length, charset, 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 →