ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Node系列 · ORM:MD5 加密

Node系列 · ORM:MD5 加密 Node系列 · ORMMD5 加密MD5 是 Node 后端最早接触的加密工具——给密码做哈希、给文件生成指纹。但 MD5 在 2004 年已被攻破不再适合用于安全场景。本章讲清楚 MD5 的本质、它在哪些场景能用、哪些场景必须换方案。一、MD5 是什么MD5Message-Digest Algorithm 5是一种单向 hash 函数特性说明输入任意长度字符串输出固定 128 位32 个十六进制字符单向无法从结果反推输入确定性同一输入永远产生同一输出快速大量数据也能毫秒级算出$echo-nhello|md5sum 5d41402abc4b2a76b9719d911017c592无论输入是 5 字节还是 5 GB输出永远是 32 个字符。二、Node 中使用 MD5npminstallmd5const md5 require(md5); md5(hello); // 5d41402abc4b2a76b9719d911017c592 md5(hello).length; // 32固定长度2.1 密码哈希// 存储密码 const hashedPassword md5(password); // 验证 if (md5(inputPassword) storedHash) { // 密码正确 }⚠️这样用不安全——见下节。三、MD5 的真实用途3.1 ✅ 适合用 MD5场景原因文件指纹 / 校验和验证文件完整性下载校验、镜像比对非安全去重给文件 / 内容生成唯一 ID如头像去重ETag 生成HTTP 缓存标识不需要防碰撞非敏感数据的快速哈希如日志指纹、临时缓存 keyconst md5 require(md5); const fs require(fs); // 计算文件指纹 const hash md5(fs.readFileSync(./big-file.zip)); console.log(SHA1: ${hash}); // 可用于校验下载完整性3.2 ❌ 不要用 MD5 的场景场景风险替代方案密码存储彩虹表 / GPU 爆破bcrypt / Argon2数字签名碰撞攻击2004 年已实现SHA-256 / SHA-3SSL / TLS 证书CA 早就不再签 MD5 证书SHA-256API 签名参数可被碰撞构造HMAC-SHA256加密敏感数据MD5 不是加密算法是哈希AES / ChaCha20四、MD5 的安全缺陷4.1 彩虹表攻击MD5 输出固定 32 字符——可以预先计算所有常见密码的 MD5// 攻击者的彩虹表 const rainbowTable { 5d41402abc4b2a76b9719d911017c592: hello, e10adc3949ba59abbe56e057f20f883e: 123456, d8578edf8458ce06fbc5bb76a58c5ca4: qwerty, // ... 几十亿条 }; // 用户登录时 if (rainbowTable[md5(input)]) { console.log(密码是:, rainbowTable[md5(input)]); }存储 MD5 哈希等于把密码明文交给攻击者——只要他有一份彩虹表。4.2 碰撞攻击2004 年王小云教授团队发布了对 MD5 的实际碰撞攻击// 两个不同的输入产生相同的 MD5 const a d131dd02c5e6eec4693d9a0698aff95c2fcab58712467eab4004583eb8f7f89a4; const b d131dd02c5e6eec4693d9a0698aff95c2fcab50712467eab4004583eb8f7f89a4; md5(a) md5(b); // true但 a ! b这意味着不能用 MD5 做文件唯一性或签名验证——攻击者能构造出看起来不同但哈希相同的内容。4.3 GPU 爆破现代 GPU 一秒能算数十亿次MD5# 8 字符密码纯字母数字GPU 一小时内能穷举完hashcat-m0-a3hash.txt?l?l?l?l?l?l?l?l五、正确替代方案5.1 密码存储bcrypt/Argon2npminstallbcryptconst bcrypt require(bcrypt); // 注册加盐 慢哈希耗时约 100ms攻击者无法高速爆破 const saltRounds 10; const hash await bcrypt.hash(password, saltRounds); // $2b$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy // 登录验证 const match await bcrypt.compare(inputPassword, hash); // true / falsebcrypt 自动生成随机盐 慢哈希自带防彩虹表。Argon2是更新的方案更安全但 Node 生态还在普及。5.2 文件指纹 / API 签名SHA-256const crypto require(crypto); const hash crypto.createHash(sha256).update(data).digest(hex); // HMAC-SHA256带密钥的 hashAPI 签名常用 const hmac crypto.createHmac(sha256, secretKey).update(payload).digest(hex);crypto是 Node 内置无需安装。5.3 选型对照场景推荐原因密码存储bcrypt/Argon2加盐 慢哈希防彩虹表 / GPU密码校验数据库存了 MD5 老数据升级方案登录时检测 MD5重置后用 bcrypt兼容期可临时保留文件指纹SHA-256无碰撞风险速度比 SHA-1 / MD5 慢但安全API 签名HMAC-SHA256带密钥的 hash无法伪造缓存 key / ETagMD5 仍可用不需要安全只需要去重六、MD5 升级路径老项目里如果用了 MD5 存密码迁移步骤const bcrypt require(bcrypt); const md5 require(md5); // 1. 用户登录时检测 async function login(email, inputPassword) { const user await User.findOne({ where: { email } }); if (!user) return null; // 2. 检查哈希格式 const isMD5 /^[a-f0-9]{32}$/.test(user.password); let isValid; if (isMD5) { // 老数据用 MD5 验证 isValid md5(inputPassword) user.password; // 3. 验证通过后升级到 bcrypt if (isValid) { const newHash await bcrypt.hash(inputPassword, 10); await user.update({ password: newHash }); } } else { // 新数据bcrypt 验证 isValid await bcrypt.compare(inputPassword, user.password); } return isValid ? user : null; }这样所有用户登录时都会被静默升级到 bcrypt——无需重置密码。七、常见误解误解真相“MD5 是加密算法”MD5 是哈希不是加密不可逆“MD5 加盐就安全了”自定义盐方案不安全用 bcrypt / Argon2“MD5 长度固定反推不出来”彩虹表 GPU 爆破可以秒破短密码“双重 MD5 更安全”不增加安全性只是计算量翻倍“截断 MD5如 md5(md5(x))[0:16]省空间”进一步削弱安全性八、最佳实践场景推荐密码存储bcrypt.hash/bcrypt.compare文件指纹crypto.createHash(sha256)API 签名crypto.createHmac(sha256, key)缓存 key / ETagmd5非安全场景仍可用老系统升级登录时检测 MD5 自动升级 bcrypt九、小结MD5 是单向 hash不是加密固定 32 字符输出不再适合安全场景密码、签名、证书——已被攻破仍适合非安全场景文件指纹、缓存 key、ETag密码存储用bcrypt/Argon2API 签名用HMAC-SHA256老项目的 MD5 密码可在登录时静默升级到 bcrypt无需重置
返回列表