也许大家还记得11年csdn的密码泄露事件,csdn使用明文来存储网站600万用户的密码⊙∀⊙!当年我就中招了,而且我基本所有的网站都使用同一个邮箱和同样的密码...

csdn密码泄露事件后,各种大小网站的密码泄露事件层出不穷。在可见的将来,泄露事件仍然会不断出现。

出来工作后,也慢慢地接触了一些安全保存用户的方法。从网站开发者和用户,两种不同的角色角度说下。

网站开发者

明文存储密码

不要使用明文在数据库里存储密码,这是最愚蠢的一种做法。编程初学者很容易就会想到这种“便捷”,他们会想到这种方式编程就简单,而且当用户忘记密码时,进数据库里查看下,就可以告诉用户了。

千万千万不要这要做,我不知道csdn出于什么目的,使用明文存储密码。这样做带来了以下的风险:

  • 所有拥有数据库权限的管理者,都可以登录任何一个用户的账号。
  • 更糟糕的是,我们的密码一般都蕴含着某种规律。例如有人喜欢用名字拼音+生日,而且往往在其他网站也使用相同的密码。

使用对称加密来加密密码

不使用明文,那加密一下就好了,这是一种正常的思维。但有些网站开发者使用对称加密的方法来加密密码,他们把用来加密的密钥,保存在服务器上。他们使用密码来加密,检验用户密码和将数据库里的加密密码解密会明文字符串。

他们使用对称加密的考虑是,他们可以随时更换密钥,来重新生成加密密码。也可以在当前使用的加密算法被破解后,更换更安全的算法。

这样的做法,其实和明文存储没有区别。当你的数据库被脱库后,你的密钥和加密算法往往一起被盗取了。入侵者可以很容易的重新算出用户的明文密码。

某些对称算法可以支持的密码位数也很有限。例如
des只支持56bit,也就是7byte的密码,虽然看起来可支持的密码数量很多,但目前的破解工具可以很容易在一天内生成des加密密码。

同时,相同的密码经过加密后,得到的是相同的加密密码。(这里的加密密码是使用sha256加密得到16进制字符串)

用户名密码加密密码
vstorm63451270e36b61dd18c107f86...b8e7f0ca41
skyking63451270e36b61dd18c107f86...b8e7f0ca41
idealideal199216fe80d03d0c074232d...75c47bcdd5

我们可以很容易知道上面vstorm和ideal使用的是相同的密码。

算法的选择也很重要。某些加密算法,加密密码就泄露了明文密码的某些信息。某些算法,加密密码的字节数,泄露了原来明文密码的字节数。例如明文是7字节,对应的加密密码都是32字节。

所以我们加密要满足下面的要求:

  • 不能从加密密码,解密得到明文密码。
  • 相同的明文密码,不能得到相同的加密密码。
  • 加密密码不能泄露明文密码的信息,例如位数。

使用hash算法(非对称算法)加密

网站开发者应该选择非对称加密,常见的md5,sha1,sha256可以将任意的明文密码,加密得到一个固定位数的加密密码。例如sha256,不论明文密码多少位,加密得到加密密码都是256位。

上面的非对称加密算法,保证了:

  • 不能从加密密码,解密得到明文密码。
  • 不能从加密密码,得到明文密码的位数信息。
  • 任何两个相同的明文密码,很难加密得到相同的加密密码。

上面的算法推荐使用sha256,因为md5和sha1,随着机器性能的不断增长,已经出现了可以从不同的明文密码,得到相同的加密字符串。

简单的python sha256加密代码

import hashlib
def encrypt_password(password:str) -> str:
            m = hashlib.sha256()
            m.update(password.encode())
            return m.hexdigest()

sha256看起来足够满足我们的要求了,但还存在着问题。

  • 相同的明文密码,加密后得到的是相同的加密密码。如果我是用户vstorm,那我知道skyking的密码和我是一样的,都是634512。
  • 而且入侵者,得到加密密码和加密算法后,可以在自己电脑,将明文密码的所有组合,使用加密算法,运算出加密密码。这就是我们常说的“彩虹表”。网络上已经公布了使用明文密码,使用上面常见的加密算法,得到的“彩虹表”。入侵者可以直接下载使用这些“彩虹表”。

“sha256彩虹表”(包含了用户常用的一些密码,如123456,qwert)

加密密码明文密码
8d969...c6c92123456
9e69e...bf37afa80qwert
.......

给每个用户的密码加点“盐”

为了对抗“彩虹表”和相同的明文密码得到相同的加密密码,可以给用户的密码“加盐”。
“加盐”,我觉得是一种很贴切的比喻。同样的食材,加不同量的盐,最终的味道就都不一样。用户的明文密码就是食材,加密密码是最后的味道。我们用一个随机的字符串,作为“盐”,它拼接到用户的明文密码前面或者后面,形成新的字符串,将新的字符串传给加密算法。
这样的做法,可以对抗“彩虹表”的攻击,因为网上公布的“彩虹表”都是没有“盐”的,入侵者只能自己“加盐”去生成彩虹表。

同时每个用户加不同的“盐”值,这样即使是相同的明文密码,最终得到的加密密码是不同的。

每个用户加不同“盐”,这样入侵者要针对每个用户生成单独的“彩虹表”,这大大加大了入侵者的运算成本。加相同的“盐”,其实和不加“盐”是一样的,入侵者只需要生成一张“彩虹表”,就可以去破解所有用户的密码。

用户明文密码加密密码
vstorm634512joiwnuica23089ec52b...d95512492
skyking634512vji91ew0f3]df89a9442...27ed86942
idealideal19921fsd0923kfdsfb84af467...f85245c8ba

简单的加盐版python sha256加密代码

import hashlib

def encrypt_password(password:str, salt:str) -> str:
        m = hashlib.sha256()
        m.update(password.encode())
        m.update(salt.encode())
        return m.hexdigest()

用户

世界没有觉得安全的系统,请记住这句话。系统总会有被攻破,数据泄露到网络的可能。系统有漏洞,人也有漏洞。
即时网站开发者已经使用非对称加密算法+不同“盐”,很多用户为了方便易记,会使用一些简单的密码,如123456789。入侵者的程序,一般都会先尝试这些简单的密码。
同时,在所有网站都使用同一个密码,也是风险很高的做法。只要有一个网站被攻破,入侵者就可以登入你所有网站的账号。特别是存在csdn这种明文存储密码的网站,入侵者根本就不需要去运算破解密码。
说说我个人一些的做法:

  • 不使用简单有规律的密码,密码的长度要较长,大写字母+小写字母+数字的结合,最好加上特殊字符。
  • 不同网站使用不同的密码。
  • 在一些小网站,如果以后都不会再上,可以使用匿名邮箱去注册账号。
  • 使用lastpassword等密码工具来生成和管理密码。
Last modification:March 26th, 2020 at 11:41 am
如果觉得我的文章对你有用,请尽情赞赏 🐶