关于登录安全和加密的问题

来源:互联网 发布:中国工控网plc编程 编辑:程序博客网 时间:2024/05/17 02:46

近来,有个朋友的网站上线了,我们一起聊了一下关于数据安全的问题,比如:防止恶意注册,恶意模拟登录,恶意访问等,因为之前做过一段时间的爬虫,在某些方面,也有一些体会,我们最后讨论到数据加密上,在网上看到一些帖子,想总结一下,资料主要来源于网上。

一、关于加密。原文
你会用什么样的算法来为你的用户保存密码?如果你还在用明码的话,那么一旦你的网站被hack了,那么你所有的用户口令都会被泄露了,这意味着,你的系统或是网站就此完蛋了。所以,我们需要通过一些不可逆的算法来保存用户的密码。比如:MD5, SHA1, SHA256, SHA512, SHA-3,等Hash算法。这些算法都是不可逆的。系统在验证用户的口令时,需要把Hash加密过后的口令与后面存放口令的数据库中的口令做比较,如果一致才算验证通过。

但你觉得这些算法好吗?我说的是:MD5, SHA1, SHA256, SHA512, SHA-3。如果你使用的是MD5算法来加密你的口令,如果你的口令长度只有小写字母再加上数字,假设口令的长度是6位,那么在目前一台比较新一点的PC机上,穷举所有的口令只需要40秒钟。而据我们了解,几乎有90%以上的用户只用小写字母和数字来组织其口令。对于6位长度的密码只需要最多40秒就可以破解了,这可能会吓到你。

如果你愿意花2000美金和一周的时间来构建一个CUDA,那么,你可以在你组建的这个集群中使用进行密码穷举运算,其速度是,1秒钟可以计算7亿个口令。对于目前实际当中使用的比较复杂的口令,其破解率也可以高达每秒一个。当然,这里说的算法是MD5,SHA之类的算法。

那么,对于这样的一种情况来说,我们怎么办?我们还是有办法的。

我们知道MD5,SHA的算法速度太快了。所以,我们需要一个“慢一点”的加密算法。呵呵。bcrypt是这样的一个算法,因为它很慢,对于计算机来说,其慢得有点BT了,但却慢得刚刚好!对于验证用户口令来说是不慢的,对于穷举用户口令来说,其会让那些计算机变得如同蜗牛一样。

因为bcrypt采用了一系列各种不同的Blowfish加密算法,并引入了一个work factor,这个工作因子可以让你决定这个算法的代价有多大。因为这些,这个算法不会因为计算机CPU处理速度变快了,而导致算法的时间会缩短了。因为,你可以增加work factor来把其性能降下来。呵呵。

那么,bcrypt到底有多慢?如果和MD5一起来比较的话,如果使用值为12的work factor的话,如果加密“cool”的话,bcrypt需要0.3秒,而MD5只需要一微秒(百万分之一秒)。也就是说,前面我们说的那个只需要40秒就可以穷举完所有的可能的MD5编码的口令的算法,在使用bcrypt下,需要12年。

这就是bcrypt给你带来的选择,你可以一个安全的口令和一个快速的加密算法,或是一个不怎么安全的口令和一个性能不好的加密算法。

二、关于数据安全原文

在一个网站的整个环节中,主要有一下几个关键点涉及到数据安全。
综合起来,密码的安全主要存在于三个方面:

1.数据库中存储密码的安全性
2.密码在网络中传输的安全性

数据库中存储密码的安全性
有一篇文章可以算是概括了这一议题:

http://zhuoqiang.me/password-storage-and-python-example.html

简单的说,数据库中密码的安全性就是假如有黑客盗取了你的数据库的数据,你如何让黑客无法破解用户的密码信息。

最简单的方法,就是在数据库中使用明文来存储用户名密码(前一段时间CSDN的密码泄漏事件算是炸开了锅,更令人吃惊的是国内第一技术网站竟然使用这种低级的方法)。这种方法非常容易破解,只要得到了用户数据,任何人直接就能获得密码信息。

第二种方法是对密码进行加密(如使用MD5、SHA算法)之后存储在数据库中。这种方法对于较复杂的密码来说黑客束手无策,但对于较常见的密码黑客在得到了数据之后依然能有效破译。有一些好事者将用户常用的密码总结出来,再使用这些加密算法得出其加密后的值,称其为彩虹表。黑客只需要用彩虹表与加密后的密码比对,依然能得到用户的原始密码。

为了克服第二种方法的缺陷,使得常见密码也能得到保护,人们发明了第三种方法:使用salt来混淆加密后的值。大体方法是,每次写入用户的密码时(如注册或修改密码),随机生成一个salt值(可能是一个随机字串或者大整数等等),并将salt与密码混合(可以是各种混合方式而不仅限于将两个串连接在一起),再进行哈希。这样,即使黑客拥有了彩虹表,也不能立即猜测出哪些哈希值对应哪些常规的密码,因为即使用户输入了常规密码,混合了salt的哈希值已经与之前大相径庭,而在salt值对于不同用户各异的情况下(如果所有用户的salt值都一样且混淆方法已知那么黑客依然可以针对常见密码与salt混合生成一个具有针对性的彩虹表),也难以对所有用户生成一个彩虹表。但黑客依然可以针对某一个用户,使用暴力穷举的方式,来破译密码。如果用户的密码长度较短且全是数字的话,由于搜索空间较小且MD5、SHA等算法由于本身特性加密过程比较快,破译也并不难。

为了克服第三种方法的缺陷,第四种方法延长了加密算法的执行时间:或者使用“stretching”增加普通MD5等快速算法的迭代次数,或者使用bcrypt这样的执行时间可配置的加密算法,来迫使黑客在暴力破译的时候需要更长的时间。由于将加密算法控制在微秒级即可给黑客的破译带来灾难性打击而同时单个用户登录时验证的耗时又不算太长,这种方法可以说有效的解决了黑客破译密码的危险。

salt与彩虹表的内容有一篇文章讲得比较详细:
http://www.libuchao.com/2013/07/05/password-salt

关于bcrypt算法可见
http://codahale.com/how-to-safely-store-a-password/

其论文见

https://www.usenix.org/legacy/events/usenix99/provos.html

这篇文章讲了php中一个通用的考虑了以上所有问题的登录验证包phpass及其验证原理,还包括一些验证安全的通用议题,还讲到了如何使用输入过滤与prepared statement结合来防止SQL注入:
http://www.openwall.com/articles/PHP-Users-Passwords

不过笔者有一个小小的疑问,做了这么多都是为了防止黑客在得知了用户数据表之后如何防止其进一步得知用户的登录密码。但再进一步说,既然黑客都得到了用户数据表了,那么是不是也能得到其他信息呢?黑客想登陆到你的帐户无非也是为了获取甚至更改你的数据(至少很多时候这样),那么数据库本身的安全是不是比用户密码存储方式的设计更重要呢。看来安全并不是一个三言两语能讲完的议题,由于本文只关注密码在存储与传输过程中的安全,所以这些内容就只能暂时忽略了。

密码在网络中传输的安全性

一篇概括性讲解:

http://zhuoqiang.me/password-transport.html

传输过程中的安全性可能比较数据库存储的安全性更重要,因为网络中的数据包极有可能被黑客截获。

最不可取的方法就是使用明文传输密码,黑客可以轻松截获http传输的数据并获知密码(且不谈黑客如何从海量数据中获取和分析与登录密码相关的数据)。

进行加密传输后依然能被轻松攻击,黑客截获后,即使不分析出密文所对应的明文,只要构造相同的http请求使用所谓的“回放攻击”,就能轻松登录用户的账户。

解决这种传输中安全问题的终极方案是使用https协议加密传输。只要在客户端输入时密码不被窃取,且ssl协议的私钥安全,这种协议就是安全的。

值得一提的是,为了避免回放攻击,可以使用nonce来解决(参见http://doc.okbase.net/parry/archive/5619.html)。这种方式虽然应用在了http自带的认证中,普通的用户登录认证也可以仿效。但是这种方法貌似还是不如https来得安全。

0 0