哈希 vs 加密 vs 编码: 区别是什么
哈希、加密和编码听起来可以互换,也常被混为一谈,但它们解决的是三个完全不同的问题。混淆它们会带来真实的安全漏洞 — 比如把本该哈希的密码拿去「加密」,或把 Base64 当作秘密来对待。本指南把这些界线划清楚,让你总能选对那一个。
编码: 让数据可安全传输
编码把数据转换成另一种格式,使其能穿过期望特定形态的系统。Base64、URL 百分号编码和 HTML 实体都是编码。其中没有密钥、也没有秘密: 任何人都能还原一个编码,而这正是要点 — 接收方需要把它解码。
当目标是兼容性而非保密时使用编码: 把二进制放进 JSON 字段、把值安全地放进 URL,或把图片作为 data: URI 嵌入。如果你把某个编码当成在「保护」数据,那就是你选错工具的警示信号。
加密: 保密但可还原
加密用密钥把数据打乱,只有持有正确密钥的人才能将其还原为原文。它在设计上是双向的 — 用密钥加密,用密钥(或其配对)解密。安全性完全依赖于密钥保密,而非隐藏算法。
当你需要存储或发送某些私密、且之后必须能读回的内容时使用加密: 传输中的消息(HTTPS)、静态文件,或保存敏感个人数据的数据库列。其决定性特征是可还原性: 在设计上,持有密钥者可以取回原文。
哈希: 单向指纹
哈希让数据通过一个单向函数,产生定长摘要。相同输入总是给出相同哈希,但没有密钥、也没有回头路 — 你无法从输出推导出输入。优秀的密码学哈希还会让寻找两个具有相同摘要的输入在实践上不可行。
用哈希来校验而非还原: 检查下载是否被篡改、比较两个文件,或对内容去重。正因为不可逆,当你根本不需要取回原文、只需确认某物是否与之匹配时,哈希正是你想要的。
把三者串起来的密码示例
密码是这三者交汇、且错误后果最严重之处。你绝不应当加密存储的密码,因为加密是可逆的 — 任何窃得密钥的人都能拿到所有密码。应改为哈希它,这样即便泄露,暴露的也只是摘要,而非密码本身。
但朴素的 SHA-256 哈希太快了: 攻击者每秒可尝试数十亿次猜测。因此密码哈希使用刻意放慢且加盐的算法,如 bcrypt、scrypt 或 Argon2。盐让相同的密码哈希出不同结果,放慢则让大规模猜测代价高昂。编码在这里完全没有角色。
一份快速决策指南
当你不确定需要哪一个时,问问自己想达成什么,并据此选择。
- 需要发送/存储数据,并在之后私密地读回确切的值? 加密。
- 只需要检查数据是否匹配、绝不需要还原? 哈希 — 若是密码,则用加盐的慢哈希(bcrypt/Argon2)。
- 需要让数据完整地穿过纯文本或纯 URL 的通道? 编码(Base64、URL 编码)— 绝不用于保密。
- 需要证明某条消息来自持有共享密钥的人? HMAC,它把哈希与一个秘密密钥结合起来。