密码还在用 MD5 加盐?不如试试 Bcrypt
很长一段时间我也是用 MD5 + 盐 来解决绝大多数密码的问题的,因为确实很方便。不过,从安全的角度来说,还是有风险,那就干脆直接上 Bcrypt 吧。
MD5 + salt
其实,在大多场景够用了,毕竟 hash 和 salt 同时被黑的概率太低了,不过其实 MD5 最大的问题不是到不是这个,而是算的太快了,随着计算能力的发展总会是有概率被破解的。
1 | password_hash = md5(password+salt) |
Bcrypt 的特点
- hash 不可逆
- 随机 salt
- 可调整的计算 cost
上代码
不多说,直接上代码,看怎么用,然后再分析。
1 | package main |
1 | # output |
golang.org/x/crypto/bcrypt
提供了 bcrypt 方法,所以使用起来非常简单的。
GenerateFromPassword
提供了加密(hash) 的方法,其中第二个参数是计算成本(工作因子),越大计算耗时越长 MaxCost 是 31CompareHashAndPassword
提供了验证的方法,用于验证用户输入的密码是否正确
最让人安心的就是,它的每次 hash 结果都都是不一样的,原因就是每次的 salt 也是不一样的。我们知道,md5 使用相同的 字符串 前后两次 hash 是一样的,从而可以验证前后用的密码是不是一样的。那么,Bcrypt 每次的 hash 都不一样,如何它是如何做验证呢?
原理一瞥
hash 结构
首先我们看看 hash 之后的结果
1 | $2a$10$nYbAG/Om/bjEGq..x5TsVOy5VIVWudVaFxchrWLWPO5M7tMDIBDVO |
- A:表示 hash 的方式,2a 代表 Bcrypt 加密版本号
- C:表示迭代次方数
- Salt:是盐
- Hash:是最后的值
分析
其实看完了结构你就不难猜测到它的原理了,说白了验证的方式很简单,就是将 hash 后的结果中的 Salt 取出来,然后对用户输入的密码再次使用相同的方式和次数进行 hash,然后比较结果,看结果是否一致。也就是说,其实 Bcrypt 的 hash 结果并不仅仅只是包含了 hash 还包含了具体的 hash 计算方式和 Salt。
总结
所以,Bcrypt 相比于 MD5 来说,我认为最关键的还是有了 cost 这个选项,并且本身的计算就比 MD5 的时间要长,大大的提高了破解的难度,而且由于 salt 的不固定,彩虹表是别想了。最后,还有一个关键点要提醒你:Bcrypt 的加密长度是有限制的,比如 golang 这里的库限制长度最大为 72,超过就会报错。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LinkinStar's Blog!
评论