"""Plugin: hash strings and identify hash types.""" from __future__ import annotations import hashlib import re from derp.plugin import command _ALGOS = ("md5", "sha1", "sha256", "sha512") # Patterns for hash identification (length -> possible types) _HASH_PATTERNS: list[tuple[str, int, str]] = [ (r"^[a-fA-F0-9]{32}$", 32, "MD5"), (r"^[a-fA-F0-9]{40}$", 40, "SHA-1"), (r"^[a-fA-F0-9]{56}$", 56, "SHA-224"), (r"^[a-fA-F0-9]{64}$", 64, "SHA-256 / SHA3-256"), (r"^[a-fA-F0-9]{96}$", 96, "SHA-384 / SHA3-384"), (r"^[a-fA-F0-9]{128}$", 128, "SHA-512 / SHA3-512"), (r"^\$2[aby]\$\d{2}\$.{53}$", 0, "bcrypt"), (r"^\$6\$", 0, "sha512crypt"), (r"^\$5\$", 0, "sha256crypt"), (r"^\$1\$", 0, "md5crypt"), (r"^[a-fA-F0-9]{16}$", 16, "MySQL 3.x / Half MD5"), (r"^\*[a-fA-F0-9]{40}$", 0, "MySQL 4.1+"), ] @command("hash", help="Hash text: !hash [algo] ") async def cmd_hash(bot, message): """Generate hash digests. !hash hello -> MD5, SHA1, SHA256 !hash sha512 hello -> specific algorithm """ parts = message.text.split(None, 2) if len(parts) < 2: await bot.reply(message, f"Usage: !hash [{'|'.join(_ALGOS)}] ") return # Check if first arg is an algorithm name if len(parts) >= 3 and parts[1].lower() in _ALGOS: algo = parts[1].lower() text = parts[2] digest = hashlib.new(algo, text.encode()).hexdigest() await bot.reply(message, f"{algo}: {digest}") return # No algorithm specified -- show all common hashes text = message.text.split(None, 1)[1] results = [] for algo in ("md5", "sha1", "sha256"): digest = hashlib.new(algo, text.encode()).hexdigest() results.append(f"{algo}:{digest}") await bot.reply(message, " ".join(results)) @command("hashid", help="Identify hash type: !hashid ") async def cmd_hashid(bot, message): """Identify a hash type by its format and length.""" parts = message.text.split(None, 1) if len(parts) < 2: await bot.reply(message, "Usage: !hashid ") return value = parts[1].strip() matches = [] for pattern, _, name in _HASH_PATTERNS: if re.match(pattern, value): matches.append(name) if matches: await bot.reply(message, f"Possible: {', '.join(matches)}") else: await bot.reply(message, f"Unknown hash format (length: {len(value)})")