如何正确加密用户密码
vim 系列很可能要坑掉了。。。Orz
很久很久以前,当人们还没有什么安全概念的时候,密码都是不加密存储。这样显然会带来很严重的问题,当你的服务器受到攻击时,用户的密码有非常非常大的概率会泄露出去,这样会给用户带来很严重的问题(参考csdn事件= =)
后来,大家觉得明文存密码太傻X了(工信部的那群**还没有这么觉得= =),于是要把密码加密,最早用的是对称加密法,就是用一个key去加密密码,然后只存储密文,用户验证时候,用同样的key解密密文就可以得到原文了。
不久以后,这个方法还是被大家觉得不太靠谱,毕竟那么多用户,用的都是同一个key,万一key泄露出去了,一样得玩完儿。那么,有没有不用key的加密方式呢?有的,one way hash。简单来讲,就是把用户密码通过不可逆的hash function映射到一个密文上。因为这个hash function的映射区间很大(当前应用比较多的是128或256bit),所以极少会发生两个不同的密码映射到同一个密文的情况。而且,因为这个hash function是不可逆的,即使有人黑掉了数据库,他仍然不知道用户的密码是什么。非要说缺点的话,就是没法帮用户“找回密码”,一般只能重新设一个。因为这个方法极大地提高了密码存储的安全性,所以这点不便就无视吧。(btw,如果哪个网站有找回密码的功能,我强烈建议大家不要再用了。。。)
故事就到这里完了?才不会呢!!!你太小看现在的黑客了!!!虽然上面那个方法看似无懈可击,但是,因为加密算法是固定的(不要试图隐藏你的算法,这是非常不靠谱的),黑客们只要花足够多的时间,就可以列出一张明文-->密文的映射表,再加上类似rainbow-table技术加速查表。一旦有人把表给列出来了,那么不管你的加密算法多么牛X,一样给破解了。不过解决方法也蛮简单的,为每个用户都随机生成一个128位的字符串,叫它salt好了,加密的时候把用户密码和salt一块儿加密,就是说,hash(password+salt)。因为这个salt是随机的,黑客得为每一个salt都写一个rainbow table,这在时间和空间上是不可能做到的,ok,safe!
很遗憾,最近几年,事情又有了变化,由于现在3d游戏市场发展的太快了,intel和nvidia研究出了各种功能强大的gpu。gpu和cpu最大的不同在于,它能够以非常快的速度进行某些算术运算。于是乎,就有人拿gpu来代替cpu来进行暴力破解了。不要觉得这没什么大不了,根据统计数据,现在主流的sha256加密算法(md5 died),原本需要1年时间破解的密码,现在用gpu只需要1个月!破解速度快了10倍多!这下真没辙了,毕竟是用的暴力破解,光增加密文长度没用,又不能强迫用户增加密码长度。。。不过呢,也别觉得压力大,现在已经有不少人着手开发了没法用gpu优化的算法,譬如说这个pbkdf2算法。
如果上面的方法还不够的话,我们还有一些物理手段来加密,譬如说令牌(不是工商银行那种纸牌)。
我最不擅长写总结了,不过还是说一些吧。这世上没有绝对安全的算法,你甚至没法证明它是安全的(证明加密算法安全,实质就是证明NP问题)。只要一个算法还没有被人成功破解,我们就可以继续信任它。只是,我希望大家在build application的时候,能够注意到这一点,毕竟,用户资料的安全,可是很重要的呢~
一个安全的个人密码系统
本文写于2011-05-28
一早发现我的gmail有从异地登录的记录,这让我很震惊。我自认为是一个很有安全观的人,密码这种东西一向是小心处理的;同时我也是一个懒人,所有网站都用了同一个密码。虽然我很莫名,但我不得不承认,我的密码在某时某地以某种方式泄露了。这次密码泄露对我来说损失惨重,我不得不手动更新了其它主要网站的密码。
痛定思痛,我决定启用一种更加安全的密码机制。其能够达到以下几个目标:
1.能够用大脑轻松记住密码或密码的构造方式
2.不同网站不同密码
3.即使密码泄露,也只影响到被泄露的那个密码,而不会被推测出其它密码
4.即使知道我的密码构成方式,也不能破解我的密码
5.即使有人通过某种神通广大的方式获得了我的所有密码,他仍然不能破解我的密码
基本思路:one way hash, 单向散列加密,不清楚的朋友们可以参考一下wiki (http://en.wikipedia.org/wiki/Cryptographic_hash_function)。我们平常用的md5,sha256都是比较出名的hash算法。
简单说来,这种加密算法有2个特性:
1. one way单向:就是说你没有能力(这里我避免使用“不能”这个说法,如果有几千年的寿命应该可以吧,呵呵)去根据密文来破解明文,不管给你多少信息都不行
2. collision free冲突免疫:你没有办法构造2段明文来让它们的密文相同
这样,一旦我用hash加密了我的密码,然后把密文当做新密码的话,任何人都没有办法破解我的密码
具体方法:
工具: hash generator(网上随便下,千万别用在线版,你发出去的http请求可不会加密),字母表转换器(自己写)。通常hash函数是将一个字节流映射到另一个字节流的,我们必须把结果转化为能够从键盘输入的字符流。
方式:alphabet(hash(key, website)) 把网站名也hash进去就保证了每个网站密码不同