编码、哈希与加密
编码、哈希与加密
本文适合
刚进入 Crypto 方向、容易把编码、哈希和加密混在一起的新手。学完你能:按字符集、长度、参数和可逆性给题目归类,再选择解码、爆破、长度扩展或进入真正的加密分析。
一句话判断
编码是换一种表示,哈希是单向摘要,加密是带密钥的可逆变换。Crypto 起手先判断它属于哪一类,否则后面的工具和攻击路线都会跑偏。
题目中常见信号
优先判断:Base64 或 Base 系列编码
优先判断:Hex、哈希、密文或整数参数
优先判断:MD5、SHA1、SHA256 或截断哈希
优先判断:对称加密
优先判断:公钥加密,常见为 RSA
优先判断:哈希认证或签名误用
优先判断:多层编码或编码套加密
核心概念
编码没有秘密,只要规则正确就能还原。哈希通常不可逆,能反查只是因为原文弱、字典命中或输出被截断。加密依赖密钥或私有参数,攻击重点是密钥来源、模式、随机数、padding 和数学关系。
S 级 WP 不能写“MD5 解密成功”。更准确的说法是:识别出 32 位十六进制 MD5,使用字典或在线库反查到弱口令;如果反查失败,就转向哈希结构、截断碰撞或题目实现问题。
最小分析流程
- 记录原始输入:字符集、长度、是否有分隔符、是否有文件头或参数名。
- 先做无损判断:Base64/Hex/URL/Unicode 转义是否能还原可读内容。
- 再判断哈希长度:MD5、SHA1、SHA256、bcrypt、JWT 等格式是否匹配。
- 如果出现密钥、IV、nonce 或 RSA 参数,进入对应加密文章。
- 每解开一层都重新判断,不把第一层结论当最终答案。
- 在 WP 中保留输入、转换命令、输出和下一步判断依据。
最小验证示例
import base64
import hashlib
import re
samples = [
"ZmxhZ3tlbmNvZGluZ19pc19ub3RfZW5jcnlwdGlvbn0=",
"5d41402abc4b2a76b9719d911017c592",
"666c61677b6865787d",
]
for s in samples:
print("\ninput:", s)
if re.fullmatch(r"[0-9a-fA-F]+", s) and len(s) % 2 == 0:
print("hex bytes:", bytes.fromhex(s)[:40])
if re.fullmatch(r"[0-9a-fA-F]{32}", s):
print("looks like MD5; md5('hello') =", hashlib.md5(b"hello").hexdigest())
try:
print("base64:", base64.b64decode(s + "==="))
except Exception as e:
print("not base64:", e)判断输出时看两件事:是否得到 flag{、可读文本、JSON、PEM、PNG/ZIP 头;如果得到的是二进制或另一串编码,就继续分类,而不是停在“解码成功”。
常见利用 / 解题路线
路线总览:
- 编码链:Base64、Hex、URL、Unicode、摩斯、Brainfuck 等逐层还原,保留每层输出。
- 哈希反查:先判断算法和盐,再用字典、hashcat、John 或题目给出的候选空间。
- 截断哈希:如果只比较前几位,估算搜索空间后爆破碰撞。
- 长度扩展:看到
md5(secret + msg)或sha1(secret || params)转向 哈希长度扩展。 - 加密题分流:出现 AES 参数看 AES基本概念,出现 RSA 参数看 RSA基本概念,出现异或看 XOR基础。
常见失败原因
排查动作:尝试补 =,检查是否 URL-safe Base64,替换 -、_
排查动作:判断是否是密文、压缩数据或 UTF-16,不要强行按 UTF-8 解释
排查动作:检查是否加盐、大小写、截断、双重哈希或自定义拼接
排查动作:每一步保存中间结果,回退上一层换编码方向
排查动作:问自己是否存在密钥和解密算法;没有就先按摘要处理
迷你案例
题目给出:
NjY2YzYxNjc3YjYzNzI3OTcwNzQ2ZjVmNzM3NDYxNzI3NDdk第一眼字符集像 Base64,解码得到:
666c61677b63727970746f5f73746172747d第二层是偶数长度 Hex,转字节得到:
flag{crypto_start}这个案例的 WP 应写成“Base64 -> Hex -> ASCII”,并说明每层判断依据:第一层字符集和长度符合 Base64,第二层只含十六进制且长度为偶数。