在互联网项目中,我们经常会遇到以下场景:
用户登录,前端输入密码传输到后端验证,用户支付,需要输入支付密码传输到后端验证。
在上述场景中都涉及到了密码的传输和存储。这就产生了一个问题,密码作为用户的敏感数据,我们该采取怎样的方案才能保证这个过程中的数据安全。
既然黑客可能获取到明文数据,那我们加密不就好了嘛。所以,在使用加密算法前我们先简单了解下加密算法。
加密主要有两种方式:对称加密和非对称加密。
对称加密是指加密和解密过程使用相同的密钥,也称为共享密钥加密。
非对称加密则使用两个密钥:公钥和私钥。公钥可以向任何人公开,用于加密数据,而私钥只有密钥的持有者才能使用,用于解密数据。
RSA加密算法是一种非对称加密算法,它由Ron Rivest、Adi Shamir和Leonard Adleman三位密学家于1977年共同提出。目前是公认的一种较为安全的加密算法。公钥私钥成对出现,用其中一个加密只能用另一个解密,通常用公钥加密私钥解密。
现在第一个传输密码的问题已经解决了,那么我们如何存储密码呢?
如果用明文存储密码(不管是存在数据库还是日志中),一旦数据泄露,所有用户的密码就毫无保留地暴露在黑客的面前。
单向加密
单向加密算法指的是只能从明文生成一个对应的哈希值,不能反过来根据哈希值得到对应的明文。经常被大家用来加密的算法有MD5和SHA系列(如SHA1、SHA256、SHA384、SHA512等)。
这样即使是我们开发人员,拿到数据都不知道用户的真实密码,安全性提高了很多,但是还不够。
通常黑客在侵入保存密码的数据库之后,他会随机猜测一个密码,生成一个哈希值。如果该哈希值在数据库中存在,那么他就猜对了一个用户的密码。如果没有猜中也没有关系,他可以再次随机猜测下一个密码进行尝试。
事实上黑客为了提高破解密码的效率,他们会事先计算大量密码对应的各种哈希算法的哈希值,并把密码及对应的哈希值存入一个表格中(这种表格通常被称为彩虹表),在破解密码时只需要到事先准备的彩虹表里匹配即可。因此现在黑客们破解仅仅只用哈希算法加密过的密码事实上已是不费吹灰之力。
加点“盐”
盐salt:一个随机的字符串,往明文密码里加盐就是把明文密码和一个随机的字符串拼接在一起。
为了应对黑客们用彩虹表破解密码,我们可以先往明文密码加盐,然后再对加盐之后的密码用哈希算法加密。由于盐在密码校验的时候还要用到,因此通常盐和密码的哈希值是存储在一起的,我们需要在数据库中为其增加对应的字段。这样我们的密码就安全多了。
拿到密文密码并且在服务器解密之后,我们用数据库中的盐(每个用户不同)来拼接明文密码,然后和数据库中的密码做对比,如果相同则登陆成功。