对基于HTTP协议的密码传输安全的一些思考(附javascript脚本实现)

  如今的网络环境日益复杂,在局域网中不可避免被他人通过 ARP 欺骗来监听网络流量,或者网关本身监听流量,抑或 ISP 监听网络流量。而在以往的 HTTP 应用中,常见的做法是将密码和其他信息一同明文发送,这就导致用户的密码受到严重的威胁。近日对这个问题做了些许不成熟的思考,写出来和大家讨论一下。

  首先说一下登录密码。用户密码通常是用哈系算法计算后保存在数据库中,常用的有 MD5(就目前来看 MD5 已被证明是不安全的)和 SHA1,并且我们暂时假定服务器本身足够安全以至未经授权的任何人不会看到这些散列值,而网络中也暂时没有中间人攻击者(在后面会提到这个问题)。

  简单的想法就是在提交之前将用户密码通过同样的哈希算法计算,将散列值送回服务器比较。然而这是一种很不成熟的想法,因为嗅探者虽然不能得到密码明文,但是他同样可以使用这一散列值欺骗服务器获得授权。因此我们要在明文中加点盐——Salt。

  所谓 Salt 就是一段字符串,将它和哈希后的密码散列按照特定方式组合起来,然后对组合后的字符串再次应用哈希算法,将散列值送回服务器,服务器使用同样的 Salt 和组合方式组合 Salt 和数据库内的散列值,然后再次应用哈希算法,将结果和客户端传来的散列值比较判断。

  这样一来,嗅探者虽然能够看到 Salt 值和最终的散列值,已经组合方式,但除非他将这一散列值还原为明文,或者他一直刷新以使得服务器返回和本次嗅探得到的 Salt 一样的 Salt。事实上这两种情况的几率都比较小,而且成本很容易高过破解成功后带来的价值,因此这一破解将变得没有任何意义。

  就目前的情况来看,登录的密码安全似乎安全性有了不少提高(对于大部分只会用一些黑客软件的所谓“黑客”来说已经是难以破解了)。接下来的问题是注册时的密码传输安全。注册的时候服务器需要获取只应用过一次哈系算法的散列值,因此不能通过 Salt 来实现,这时就要用 RSA 非对称加密对散列值进行加密传输,然后在服务器端解密,这个想法比较简单。

  然而这样的传输方式对中间人攻击防范很弱,尤其是在注册的时候,中间人可以伪造一对 RSA 密钥,并替换发给用户的密钥,这样他就可以轻松的拿到一次哈系后的密码散列,甚至可以去掉相关的加密部分,使密码明文传送到攻击者那里。而这种攻击需要攻击者自行根据不同的网站编写不同的攻击程序,难度较高,因此只能说这些方法在安全性上有些许提高。

  最后简单说一下 .NET 下的实现方式。随机的 Salt 可以通过 RNGCryptoServiceProvider 生成,哈系算法建议使用 SHA1CryptoServiceProvider,RSA 算法则使用 RSACryptoServiceProvider,其中 Salt 和 RSA 的私钥可以保存在用户的 Session 中并加入生成时间,控制有效期。客户端方面需要自行编写 javascript 脚本实现 SHA1 和 RSA 加密,稍后我会整理出这 2 个脚本文件。此外,对于可以使用 AJAX 的网站,可以在点击提交时获取 Salt 或 RSA 公钥,然后计算后再提交,并减小有效期,增加中间人攻击的难度。过段时间我会给出完整的代码。

  另外还要提一下,任何安全性的增加都是牺牲性能的下降,在这里,客户端的加密函数较为庞大,此外客户端的 RSA 加密在我本人的 Core 2 Duo T9300 + 4GB 内存的笔记本上使用 1024 位密钥加密大概要好时 240 毫秒左右,而 SHA1 加密也要好费 30 毫秒左右。

  javascript 脚本实现参见 http://www.cnblogs.com/hust21941/archive/2008/08/16/1269463.html

posted @ 2008-08-15 12:04  田嵩  阅读(3561)  评论(31编辑  收藏  举报