网站开发一般都会涉及到数据库设计,而数据库设计大多数情况都会涉及到密码的保存。近几年发生过多起网站用户信息泄露事件:CSDN 用户账号及明文密码泄露网易邮箱过亿用户数据泄露 等等。通过这些事件,大家对网络安全也越来越重视,而信息安全中最重要的一项就是密码,用户如何选择密码和保存密码是另外一个话题,本文主要探讨服务器端(网站)是如何保存密码的。

下面首先介绍三种安全性较差(不推荐)的保存方法,然后介绍安全性较好(推荐)的保存方法。

安全性较差

1. 明文保存

最简单的处理方式就是不做处理,用户密码是什么就保存什么。

CSDN 事件中,官方声明泄露的数据是 2009 年的备份数据库。如果账号是在 2009 年之后注册的,那么就没有遭到泄露,而在那之前的则都泄露了。这就说明在 2009 年数据库备份之前,CSDN 的网站数据库中是把用户密码保存成明文的。

明文保存当然是最不安全的,尤其是很多人同一个密码会用在多个网站上。而类似 CSDN 这样泄露的数据就会被人利用做成社工库,比如 这个这个

现在的数据库中绝对不应该保存明文密码!

2. 加密保存

如无特别说明,本文所指的加密都是指可逆加密,如 AES, RSA 等算法的加密方式。

有时候,为了某些特殊的原因,网站可能需要知道用户的明文密码。但是为了降低密码泄露的风险,会对密码做加密然后保存。在有需要的时候,再将保存的数据解密得到明文密码。

相对于明文保存,这种方法看起来更安全。但实际上,安全性并没有提高多少。因为,现在安全的中心在于保护加密密钥的安全,一旦加密方法和加密密钥泄露出去了,数据库中加密后的密码就和明文无异了,所以这种方法只不过是将安全性转移了而已,除了为达到某些特殊的目的之外,并没有多大用处。

根据网上公开的信息,很少看到有采用这种方法的。

3. 简单哈希保存

相比前两种而言,这种方式在安全性上有很大的提升。因为一般来说哈希是不可逆的,所以即便拿到了数据库中的数据,从哈希值倒推回明文密码的可能性也是很小的。但是这并不意味着绝对安全,因为有其它方式可以破解出明文密码来。

在实际的使用中,主要有两种不同的使用方法:只对明文密码做哈希;在明文密码上加 ,再做哈希。很显然后一种方法的安全性较高。

哈希方法的专业称呼是 KDF: Key Derivation Function。下面根据哈希算法的不同,分别介绍。

3.1 MD5

在早期的网站设计中,由于 MD5 速度快,并且没有出现相应的攻击方法,因此应用最为广泛。然而,速度快是它的优点也是它的最大缺点。因为只需要构造一个表,把常见密码及其对应的 MD5 值保存下来,碰到 MD5 后的密码值,很容易查到原始的明文密码,尤其是在没有加盐或者盐比较简单的情况下。

现在已经有一些网站提供查找 MD5 对应的原始串的服务,比如 https://crackstation.net/ , http://md5decrypt.net/en/ , https://isc.sans.edu/tools/reversehash.html 等。它们的原理其实就是维护 彩虹表 。比如输入 7cbb3252ba6b7e9c422fac5334d22054 查询出来的原始串是 q1w2e3 ,这也是很常见的一个密码。

彩虹表的存在让针对 MD5 存储密码的方法变得不再安全,随着计算速度的快速提高,攻击方法的提高,针对 MD5 的攻击越来越容易,因此在现代的系统中,是不应该出现只用 MD5 对(加盐)密码做哈希的设计。关于彩虹表的介绍和下载见 RainbowCrack

3.2 SHA1, SHA256 等

由于 MD5 的安全性较差,因此有用 SHA1, SHA256 等更安全的算法来代替 MD5。其实在安全性上,这些方法比 MD5 其实并没有高出很多来,因为彩虹表仍然是离线生成的,只是所需时间比 MD5 多点而已,因此在现代的系统中仍然不能只使用 SHA1 或 SHA256 等摘要算法来(加盐)对密码做哈希再保存。

安全性较好

1. PBKDF2

PBKDF2 的全称是 Password-Based Key Derivation Function 2 ,详细介绍可以见 wiki。 它的做法是将密码加盐后做很多遍哈希,比如 1000 次,这样就将破解难度提高了 3 个数量级。但是如果使用 ASIC 或者 GPU 的话,能大大降低破解难度。此外,ASIC 在比特币挖矿中得到了广泛的应用,目前,比特币挖矿基本都是 ASIC 的天下,GPU 都没有多少市场了。

2. bcrypt

bcrypt 的详细介绍见 wiki 。BSD 和一些 Linux 系统 (比如 SUSE Linux)就是用它来储存密码的。/etc/shadow 文件中密码那一项如果是以 $2a$, $2b$ 或者 $2y$ 开头的话,就说明是用 bcrypt 加密的。

3. scrypt

由于使用专门硬件(比如 ASIC)能大大降低密码破解的难度,scrypt 就应运而生了。原始的论文见 这里

科学和技术的进步总是很快的,现在看起来安全的方法也许几年后就会变得不再安全,因此在设计系统时,需要考虑扩展性,以便以后能平滑升级到更安全的加密方法。没有永远和绝对的安全,只有好的设计和跟上时代发展的技术的使用,才是安全的。