你写的代码里,有没有偷偷用 MD5 存密码?
如果有的话,这篇文章会救你一命。
哈希值这三个字,程序员肯定都听过。MD5、SHA256、Bcrypt……各种算法长得差不多,到底该用哪个?什么时候用哪个?
别急。今天拿 Navbox 上的哈希生成器当工具,把开发中最常见的 6 种场景讲清楚。全部实测,附代码和配置。
场景一:用户密码存储——用 Bcrypt,别用 MD5
这是我见过最多的错误。
很多老项目的用户表里,密码字段存的是 MD5(password)。有人还会加盐:MD5(password + salt)。
听着挺安全对吧?其实不是。
MD5 的计算速度太快了。现代 GPU 每秒可以算几十亿次 MD5。攻击者拿到你的哈希值后,用彩虹表或者暴力破解,几分钟就能还原出大部分弱密码。
正确做法:用 Bcrypt。
Bcrypt 的设计思路完全不同——它故意让计算变慢。通过调整 Salt Rounds(计算轮数),每次哈希都需要几百毫秒。攻击者破解的速度直接降到几十次/秒。
打开 Navbox Bcrypt 哈希生成器,输入密码,选 Salt Rounds 12,点生成。你会看到输出长这样:
$2a$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl769iz05QXZ1GZz7sR1Fm7Ki
这个字符串里包含了算法版本(2a)、Salt Rounds(12)、随机盐值,还有最终的哈希值。
验证密码时:用 Bcrypt 的 check() 函数,把用户输入的密码和库里存的哈希值传进去,它会返回 true/false。注意——不要自己重新算一遍再对比,那样盐值会对不上。
实战代码(Node.js):
const bcrypt = require('bcrypt');
// 注册时
const saltRounds = 12;
const hash = await bcrypt.hash(plainPassword, saltRounds);
// 存到数据库
// 登录时
const isMatch = await bcrypt.compare(inputPassword, storedHash);
if (isMatch) { /* 登录成功 */ }
场景二:文件完整性校验——用 SHA256
你有没有遇到过这种情况——下载了一个安装包,安装后跑起来报错,怀疑文件损坏了。
这时候哈希值就是救星。
开发团队分发文件时,会同时给出文件的 SHA256 哈希值。你下载完文件后,本地算一遍哈希,跟团队给的值对比。完全一致,文件就没问题。不一样,说明下载过程中有数据损坏,重新下载。
打开 Navbox 哈希生成器,粘贴文件内容(或者上传文件),一键生成 MD5、SHA1、SHA256 三种哈希值。
生产环境最佳实践:
- 下载大文件(镜像、安装包)时,永远先验哈希
- SHA256 是目前公认安全的校验算法
- 不要依赖 MD5 做安全校验,碰撞攻击已经公开可用
# Linux/Mac 终端一键验证
sha256sum filename.iso
# 输出: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 filename.iso
场景三:API 签名防篡改——HMAC-SHA256
做后端接口的人都知道:API 调用必须防篡改。
攻击者可以拦截请求、修改参数、重新发送。怎么保证请求是原始发送的?
HMAC(哈希消息认证码) 是标准答案。
简单说,就是拿请求内容 + 一个只有你和 API 提供方知道的 secret key,算一遍哈希。接收方收到请求后,用同样的 key 和同样的内容算一遍,对比哈希值是否一致。
打开 Navbox 哈希生成器,选 SHA256,输入你的 secret key + 请求内容,就能得到签名。
实战代码(Python):
import hashlib
import hmac
import base64
secret_key = "my-secret-key-12345"
message = "GET /api/users?page=1"
# 生成签名
signature = hmac.new(
secret_key.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
# 把签名放进请求头
headers = {
"X-API-Signature": signature
}
前端调用时带上这个签名,后端验证通过后才处理请求。每次请求的 message 可以包含时间戳,防止重放攻击。
场景四:数据去重——MD5 最快
你做过数据清洗吗?几十万条记录里找出重复的。
最快的办法就是给每条记录算个 MD5 哈希值,然后对比哈希值。相同的哈希值 = 相同的内容。
MD5 的优势是快。你的数据量越大,这个优势越明显。
打开 Navbox 哈希生成器,批量粘贴你的数据(每行一条),一键生成所有行的 MD5。
注意:MD5 的碰撞问题(两个不同内容算出相同哈希)在数据去重场景下完全可以忽略。你需要的是"同内容同哈希",不需要"不同内容不同哈希"。
SQL 示例:
-- 找重复邮件
SELECT email, COUNT(*) as cnt
FROM users
GROUP BY email
HAVING cnt > 1;
-- 或者加哈希字段加速查询
ALTER TABLE users ADD COLUMN email_hash VARCHAR(32);
UPDATE users SET email_hash = MD5(email);
CREATE INDEX idx_email_hash ON users(email_hash);
场景五:代码版本标识——用短哈希
Git 提交用 SHA1 哈希做版本号,这个你们肯定见过:
commit a1b2c3d4e5f6...
你自己在项目里也可以用类似思路。每次代码发布时,自动生成一个短哈希作为版本号,部署到服务器后记录这个哈希,出问题回滚时知道回滚到哪个版本。
# 生成当前代码的短哈希
git rev-parse --short HEAD
# 输出: a1b2c3d
或者用 Navbox 哈希生成器 对代码目录打包后的内容算 SHA256,作为发布版本的唯一标识。
场景六:密码短语生成器——好记又安全
前面说了 Bcrypt 存密码。但密码本身呢?你自己的密码怎么生成?
Navbox 密码生成器 支持自定义长度和字符类型,生成纯随机密码。
但更好的方案是密码短语:
correct-horse-battery-staple
4-5 个随机单词拼起来。长度长(20+ 字符),好记,安全。
Navbox 随机密码短语生成器 就是这个用的。每次生成 5 个不相关的单词,用分隔符连起来。
6 种场景一张表总结
| 场景 | 推荐算法 | 工具 |
|---|---|---|
| 密码存储 | Bcrypt (Rounds 12+) | Bcrypt 哈希生成器 |
| 文件校验 | SHA256 | 哈希生成器 |
| API 签名 | HMAC-SHA256 | 哈希生成器 |
| 数据去重 | MD5 | 哈希生成器 |
| 版本标识 | SHA256 短哈希 | 哈希生成器 |
| 密码生成 | 随机密码短语 | 随机密码短语生成器 |
写在最后
哈希值这东西,用对了是安全,用错了是隐患。
MD5 不是不能用了,只是别用在安全场景里。文件校验、数据去重、版本标识,这些场景下 MD5 照样好用。
下次碰到需要哈希的地方,先想清楚你的需求是什么,再选算法。别无脑 MD5,也别盲目上 SHA256——合适比先进更重要。
现在就去 Navbox 哈希生成器 试试手,把你项目里该改的哈希算法都改一遍。