← 返回博客

bcrypt vs MD5:密码存储的正确选择

2026-04-18 · 5 分钟阅读

核心问题:MD5 为什么不能存储密码

MD5 存储密码的根本问题是速度。MD5 每秒可以计算数十亿次,这对于数据处理是优点,但对于密码安全是致命缺陷。当数据库被泄露,攻击者拿到 MD5 哈希后,可以使用以下方法快速破解:彩虹表(预计算的哈希→密码对照表)、暴力破解(在现代 GPU 上每秒尝试数十亿个密码组合)、字典攻击(使用常见密码词典)。大多数弱密码的 MD5 可以在秒级甚至毫秒级内被破解。

bcrypt 的设计哲学:故意慢

bcrypt 由 Niels Provos 和 David Mazières 于 1999 年设计,核心理念是"故意慢"——通过 cost 参数控制计算复杂度。cost=10 意味着 2 的 10 次方(1024)轮 key schedule 迭代。在现代计算机上,bcrypt(cost=12) 大约需要 100–300 毫秒,而 MD5 只需要微秒。这个差异让暴力破解的代价增加了几个数量级:MD5 GPU 破解速度 ~100 亿/秒,bcrypt cost=12 GPU 破解速度 ~10万/秒,相差约 10 万倍。

bcrypt 的内置安全特性

/* bcrypt output format */
$2b$12$[22-char salt][31-char hash]
  ^  ^  ^
  |  |  |-- 128-bit salt (22 Base64 chars)
  |  |-- cost factor (2^12 = 4096 iterations)
  |-- bcrypt version (2b = current standard)

在常见框架中使用 bcrypt

// Node.js
const bcrypt = require('bcryptjs');

// Hash (async)
const hash = await bcrypt.hash(password, 12); // cost=12
// Store hash in database

// Verify
const isValid = await bcrypt.compare(password, storedHash);

// Python (Django)
from django.contrib.auth.hashers import make_password, check_password
hash = make_password(password)  # Uses PBKDF2 by default, can configure bcrypt
is_valid = check_password(password, hash)

# PHP
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$isValid = password_verify($password, $hash);

# Go (golang.org/x/crypto/bcrypt)
hash, _ := bcrypt.GenerateFromPassword([]byte(password), 12)
err := bcrypt.CompareHashAndPassword(hash, []byte(password))

bcrypt 的局限性

bcrypt 有一个实际局限:密码长度限制为 72 字节。超过 72 字节的字符(约 72 个 ASCII 字符)不会影响哈希结果。对于支持超长密码的系统,可以在 bcrypt 之前先用 SHA256 哈希密码(将任意长度压缩为 32 字节),再将 SHA256 哈希值(十六进制字符串或 Base64)作为 bcrypt 的输入。

2025 年的建议:Argon2id 优先

虽然 bcrypt 仍然被认为安全,但 2025 年新项目的首选是 Argon2id,这是 2015 年密码哈希竞赛的获胜者。与 bcrypt 相比,Argon2id 增加了内存复杂度参数,使其对 GPU 并行攻击更具抵抗力,且没有 72 字节的长度限制。OWASP 在其密码存储指南中将 Argon2id 列为首选,bcrypt 作为备选。

迁移指南:从 MD5 密码迁移到 bcrypt

如果你的系统使用了 MD5 存储密码,以下是迁移到 bcrypt 的策略:在用户成功登录时(此时你有明文密码),将 MD5 哈希替换为 bcrypt 哈希;对于长期未登录的用户,可以先对 MD5 哈希值本身进行 bcrypt 处理("哈希的哈希"),在用户下次登录时再完成完整迁移;在数据库中添加标识字段,记录每个用户的密码哈希类型。

立即免费使用相关工具

免费使用 →