Password bcrypt scrypt

本文讲述了安全存储密码的最佳实践,强调避免使用加密或简单的哈希算法,推荐使用bcrypt和scrypt等算法来保护密码安全。
刚好坚果云博客写了一篇这样的文章【1】, 讲述如何存储密码才安全。完整内容可以查看【1】原文。

简单而言,存储bcrypt, scrypt等算法输出的内容,不要用salted hash的方式存储密码,不要用加密的方式存储密码,当然,更不要明文存储。

顺带说一句,任何情况下尽可能的不要使用md5算法,而使用SHA系列的哈希算法。因为md5算法在很多地方被证明是很容易冲突的【2】,另外md5的性能优势也完全可以忽略不计。

为什么不能加密存储?
加密存储的方式其实和明文存储没有区别。密码加密后一定能被解密获得原始密码,因此,该网站一旦数据库泄露,所有用户的密码本身就大白于天下。另外,管理员也存在获取原始密码,利用同样的帐号登陆其他互联网服务的可能。

为什么不能用Hash存储?
单向Hash算法(MD5, SHA1, SHA256等)可以保证管理员几乎不能恢复原始密码。但它有两个特点:
1)从同一个密码进行单向哈希,得到的总是唯一确定的摘要
2)计算速度快。随着技术进步,尤其是显卡在高性能计算中的普及,一秒钟能够完成数十亿次单向哈希计算

结合上面两个特点,考虑到多数人所使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合, 然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为rainbow table【3】。
更糟糕的是,一个攻击者只要建立上述的rainbow table,可以匹配所有的密码数据库。

为什么不能用Salt + Hash的方式存储?
将明文密码混入“随机因素“,然后进行单向哈希后存储,也就是所谓的”Salted Hash”。
这个方式相比上面的方案,最大的好处是针对每一个数据库中的密码,都需要建立一个完整的rainbow table进行匹配。 因为两个同样使用“passwordhunter”作为密码的账户,在数据库中存储的摘要完全不同。
10多年以前,因为计算和内存大小的限制,这个方案还是足够安全的,因为攻击者没有足够的资源建立这么多的rainbow table。 但是,在今日,因为显卡的恐怖的并行计算能力,这种攻击已经完全可行。

为什么bcrypt, scrypt等算法能保证密码存储的安全性?
这类算法有一个特点,算法中都有个因子,用于指明计算密码摘要所需要的资源和时间,也就是计算强度。计算强度越大,攻击者建立rainbow table越困难,以至于不可继续。

也就是说,故意延长一个密码匹配的计算时间,如果一个密码匹配需要1秒钟,那么匹配1000万个密码组合就需要115天,这个开销就非常大。

另外,这类算法也可以保证即使计算能力不断提高,只要调整算法中的强度因子,密码仍然不可能被轻易的攻破,同时不影响已有用户的登陆。关于这些算法的具体优劣,请参考【1】

【1】 blog.jianguoyun.com/?
【2】 marc-stevens.nl/researc
【3】 en.wikipedia.org/wiki/R


作者:韩竹
链接:http://www.zhihu.com/question/20479856/answer/15243887
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
开启哈希函数(如 bcryptscrypt)作为服务器验证密码的一种安全实践,通常包括以下几个步骤: 1. **选择库**:首先,确定你的编程语言环境,比如在 Python 中可以使用 `bcrypt` 库,在 Node.js 中则有 `bcryptjs`,而 `scrypt` 可能需要专门的库支持。 2. **安装依赖**:在你的项目中安装相应的哈希库,例如在命令行运行: - 对于 Python: ```bash pip install bcrypt ``` - 对于 Node.js: ```bash npm install bcryptjs ``` 3. **用户注册处理**:当用户注册时,从表单获取明文密码,然后调用哈希函数对密码进行加密: - Python 示例(bcrypt): ```python import bcrypt plain_password = user_input["password"] hashed_password = bcrypt.hashpw(plain_password.encode('utf-8'), bcrypt.gensalt()) ``` - Node.js 示例(bcryptjs): ```javascript const bcrypt = require("bcrypt"); const password = "user_password"; const saltRounds = 10; const hashedPassword = await bcrypt.hash(password, saltRounds); ``` 4. **存储哈希值**:将生成的哈希密码存入数据库,而不是原始密码。 5. **登录验证**:当用户登录时,取出数据库中的哈希密码,再与用户输入的密码做比较: - 比较示例(Python): ```python isMatch = bcrypt.checkpw(user_input["password"].encode('utf-8'), hashed_password) ``` - 比较示例(Node.js): ```javascript const isMatch = await bcrypt.compare(password, hashedPassword); ``` 6. **设置盐值**:哈希函数通常会自动加入随机盐值,如 bcrypt 的 `gensalt()`,这增加了破解的难度,因为每次哈希结果都会有所不同。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值