RTX 5090 一小时横扫 MD5:.NET 开发者该用 BCrypt 了
近日消息,卡巴斯基近日发布研究报告,通过一块愛GeForce RTX5090显卡,对采用MD5算法哈希存储的超过2.31亿个唯一密码进行暴力破解测试,最终结果显示:60%的密码可在一小时内攻破,其中48%更是在短短60秒内即告沦陷。
这其实不意外。MD5设计出来本就不是给密码用的——它是做文件校验的,越快越好。但密码存储正好相反,越慢越安全。数据库一泄露,攻击者拿着哈希值离线跑字典,算法越快他越开心。
今天聊聊 BCrypt——这个 1999 年出生、故意把自己设计得很慢的老家伙,为什么到了 2026 年,依然稳坐密码安全第一梯队。
🔗 .NET BCrypt库:https://github.com/BcryptNet/bcrypt.nethttps://github.com/BcryptNet/bcrypt.net
🔍 MD5为什么不行,BCrypt为什么行?
MD5一秒能算十亿次。BCrypt故意慢——加了个叫cost factor的参数,调多少就跑多少轮耗CPU的操作。cost=12的时候一秒只能算几百次,攻击者用同样显卡跑BCrypt,效率直接降了几个数量级。
你选BCrypt,本质上不是追求“破不了”,是追求“破起来不划算”。
🧬 BCrypt怎么比的?盐和cost都藏哈希里了
你注册时,BCrypt做了三件事:随机生成一个128位盐、按你给的cost跑2^cost轮Blowfish密钥编排、把盐+cost+最终哈希拼成一个字符串扔给你。
你存进数据库的就是这一整串:
登录时调用Verify(用户输入的明文, 数据库里的哈希),它内部三步走:
1. 拆哈希——从数据库那串里提取出盐和cost。2. 重算——拿用户刚输入的明文 + 刚拆出来的盐 + 同样的cost,重新跑一遍Blowfish密钥编排。3. 比对——新算出来的哈希和数据库里那串后半截哈希,一样就过。
所以你不用管盐、不用管cost。注册时一次性存进去,验证时BCrypt自己知道怎么拆开用
⚡ .NET里怎么用?
WebAPI里就两个地方用到:注册时存,登录时取出来验。
dotnet add package BCrypt.Net-Next注册:
var hashedPassword = BCrypt.Net.BCrypt.HashPassword(dto.Password); var user = new User { Username = dto.Username, PasswordHash = hashedPassword }; _db.Users.Add(user); await _db.SaveChangesAsync();登录:
var user = await _db.Users.FirstOrDefaultAsync(u => u.Username == dto.Username); if (user == null || !BCrypt.Net.BCrypt.Verify(dto.Password, user.PasswordHash)) return Unauthorized("用户名或密码错误");就俩API。不用管盐,不用管拼接。Verify会把数据库里的哈希拆开,自己提取盐和cost重新算一遍再比对。
🔄 老项目MD5怎么迁移?
你不知道用户的明文密码,也不需要知道——用户自己知道。
加个
password_hash字段专门存 BCrypt。登录时先看这个字段有没有值:如果有,直接 BCrypt 验证;如果没有,就用旧的password_md5字段做 MD5 验证,通过后立刻拿这次输入的明文生成 BCrypt 哈希,存入password_hash字段。下次登录直接走 BCrypt,永远不再碰 MD5。
💎 总结
MD5追求快,这种快在密码泄露瞬间就从特性变成漏洞。BCrypt走相反的路——故意慢,把攻击成本拉高到不划算。盐和cost全藏在哈希串里,注册时一次性存进去,验证时库自己拆开用。
安全圈有个说法我很认同:没有绝对安全的系统,只有让攻击者觉得不划算的系统。BCrypt做的事就是这个——把破解成本拉高到没人愿意付的地步。这就够了。
