如何安全的存储密码

如何安全的存储密码

过去一段时间来, 众多的网站遭遇用户密码数据库泄露事件。层出不穷的类似事件对用户会造成巨大的影响,因为人们往往习惯在不同网站使用相同的密码,一家 “暴库”,全部遭殃。

那么在选择密码存储方案时, 容易掉入哪些陷阱, 以及如何避免这些陷阱? 坚果云,作为一个用于同步、备份文件的云存储服务提供者,在安全方面有一些心得,记录于此,与大家分享。

菜鸟方案

直接存储用户密码的明文或者将密码加密存储。

曾经有一次我在某知名网站重置密码,结果邮件中居然直接包含以前设置过的密码。我和客服咨询为什么直接将密码发送给用户,客服答曰:“减少用户步骤,用户体验更好”;再问 “管理员是否可以直接获知我的密码”, 客服振振有词:“我们用 XXX 算法加密过的,不会有问题的”。

殊不知,密码加密后一定能被解密获得原始密码,因此,该网站一旦数据库泄露,所有用户的密码本身就大白于天下。

以后看到这类网站,大家最好都绕道而走,因为一家“暴库”,全部遭殃。

入门方案

将明文密码做单向哈希后存储

单向哈希算法有一个特性,无法通过哈希后的摘要(digest) 恢复原始数据,这也是 “单向” 二字的来源,这一点和所有的加密算法都不同。常用的单向哈希算法包括 SHA-256, SHA-1, MD5 等。例如,对密码“passwordhunter” 进行 SHA-256 哈希后的摘要 (digest) 如下:

bbed833d2c7805c4bf039b140bec7e7452125a04efa9e0b296395a9b95c2d44c

可能是 “单向” 二字有误导性,也可能是上面那串数字唬人,不少人误以为这种方式很可靠, 其实不然。

单向哈希有两个特性:

1)从同一个密码进行单向哈希,得到的总是唯一确定的摘要

2)计算速度快。随着技术进步,尤其是显卡在高性能计算中的普及,一秒钟能够完成数十亿次单向哈希计算

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

更糟糕的是,一个攻击者只要建立上述的rainbow table,可以匹配所有的密码数据库。仍然等同于一家 “暴库”,全部遭殃。以后要是有某家厂商宣布 “我们的密码都是哈希后存储的,绝对安全”,大家对这个行为要特别警惕并表示不屑。有兴趣的朋友可以搜索下,看看哪家厂商躺着中枪了。

进阶方案:

将明文密码混入 “随机因素 “,然后进行单向哈希后存储,也就是所谓的”Salted Hash”。

这个方式相比上面的方案,最大的好处是针对每一个数据库中的密码,都需要建立一个完整的 rainbow table 进行匹配。 因为两个同样使用 “passwordhunter”作为密码的账户,在数据库中存储的摘要完全不同。

10 多年以前,因为计算和内存大小的限制,这个方案还是足够安全的,因为攻击者没有足够的资源建立这么多的 rainbow table。 但是,在今日,因为显卡的恐怖的并行计算能力,这种攻击已经完全可行。

专家方案

故意增加密码计算所需耗费的资源和时间,使得任何人都不可获得足够的资源建立所需的 rainbow table。

这类方案有一个特点,算法中都有个因子,用于指明计算密码摘要所需要的资源和时间,也就是计算强度。计算强度越大,攻击者建立 rainbow table 越困难,以至于不可继续。

这类方案的常用算法有三种:

1)PBKDF2(Password-Based Key Derivation Function)

PBKDF2 简单而言就是将 salted hash 进行多次重复计算,这个次数是可选择的。如果计算一次所需要的时间是 1 微秒,那么计算 1 百万次就需要
1 秒钟。假如攻击一个密码所需的 rainbow table 有 1 千万条,建立所对应的 rainbow table 所需要的时间就是 115 天。这个代价足以让大部分的攻击者忘而生畏。

美国政府机构已经将这个方法标准化,并且用于一些政府和军方的系统。 这个方案最大的优点是标准化,实现容易同时采用了久经考验的 SHA 算法。

2) bcrypt

bcrypt 是专门为密码存储而设计的算法,基于Blowfish 加密算法变形而来,由 Niels Provos 和 David Mazières 发表于 1999 年的 USENIX。

bcrypt 最大的好处是有一个参数(work factor), 可用于调整计算强度,而且 work factor 是包括在输出的摘要中的。随着攻击者计算能力的提高,使用者可以逐步增大 work factor,而且不会影响已有用户的登陆。

bcrypt 经过了很多安全专家的仔细分析,使用在以安全著称的 OpenBSD 中,一般认为它比 PBKDF2 更能承受随着计算能力加强而带来的风险。bcrypt 也有广泛的函数库支持,因此我们建议使用这种方式存储密码

3) scrypt

scrypt 是由著名的 FreeBSD 黑客 Colin Percival 为他的备份服务 Tarsnap 开发的。

和上述两种方案不同,scrypt 不仅计算所需时间长,而且占用的内存也多,使得并行计算多个摘要异常困难,因此利用 rainbow table 进行暴力攻击更加困难。

scrypt 没有在生产环境中大规模应用,并且缺乏仔细的审察和广泛的函数库支持。但是,scrypt 在算法层面只要没有破绽,它的安全性应该高于 PBKDF2 和 bcrypt。

采取行动:

看到这里,如果你产生了危机感,那么就行动起来:

1)如果你是普通用户,那么我们建议采取这种方案,对不同的网站使用不同的密码;

2)如果你是开发人员, 并且现在已经采取了简单的 MD5 哈希存储,请关注我们的后续文章。我们会讲述在保证用户正常登陆的情况下,如何进行密码迁移。

编辑于 2017-09-08