题注
这接近10天的时间一直忙着写论文,技术博客也就有一个多星期没有更新了。今天把“初定稿”版本交给了Boss,自己也终于稍微松口气,可以更新一下技术博客啦,这必须得普天同庆啊!
最近攒的需要更新的技术博客也比较多,我得一个个写,各位看官还请静待更新啊。第一个需要和大家谈谈的是一个密码学原型函数(Cryptographic Primitive)。本来呢,自己是做密码学的,这种东西写出来看的人也不多,大家用到的机会也不大。不过,这次介绍的一个原型函数很有意思,是一类特殊的Hash,而且这个Hash还特别颠覆Hash本身的概念。所以我觉得有必要跟大家介绍一下~
另外呢,在实现的过程中实际上我也参考了一些别人的代码,但是很多人博客上对于Hash这个函数的概念理解都是错误的。我觉得自己有必要跟大家分享一些密码学中的基础知识,毕竟在信息时代,知道一些信息安全的知识也是必不可少的。信息安全嘛,朝阳企业,真心希望大家看到我的博客能有所收获,有所启发,或者指出我博客中说的不对的地方,大家一起努力一起提高嘛!
背景知识
Hash的概念
首先介绍一些什么叫做Hash函数。我们切入一个简单应用场景里面:登录网站时如何验证密码的正确性?看到这个场景,可能很多人都会不约而同的说:网站存有我们的密码嘛,验证的时候看看密码相等不相等不就可以了嘛?这种验证方法经常会出现在一些简单的网站系统中,甚至旧版的CSDN也犯了类似的错误,因此导致所有用户密码因为数据库本身数据的泄露而泄露。
其实仔细想一想,对比输入和存入的密码是否一致这种方法实在是不太安全。我们通信的时候,实际上通信内容本身大家都是可见的。在网络中所有通信的数据,用一些简单的方法就可以获得通信过程中的所有数据(比如使用Sniffer工具)。如果大家密码这么传输,那么稍微有些网络技术的爱好者们就可以很容易地获取到大家的密码。
那么,怎么能在公开验证数据的前提下,保证验证的正确性呢?最简单也是最通用的方法就是使用所谓的Hash函数了。
Hash函数,说白了,就是以任意长的字串作为输入 ,经过计算后输出一个固定长度的字串。而且,这个计算过程是不可逆的,也就是说,如果只给你输出的固定长度的字串,几乎不可能算出原始的字串。
我们举个简单的例子:给定输入为12345,我们计算1*2*3*4*5=120作为输出结果。那么,如果我们知道12345,当然可以很容易算出输出结果了。但是,反过来,如果给出了输出的结果120,似乎比较难得到12345这个原始的数。
Hash函数比上面的要求更高,它要求有如下两点:
1. 对于任意m作为输入,得到输出的结果,很难找到另一个输入m' \neq m,使得m'的Hash结果也为同样的输出,即Hash(m) = Hash(m')。这一性质成为广义碰撞抵抗性。
2. 进一步,很难找到任意两个m和m',使得Hash(m) = Hash(m')。这里我们没有固定住m和m',因此这一要求比第一个要求更为严格。这一性质成为严格碰撞抵抗性。
如果我们有这样一个Hash函数,那么密码的验证就简单了:当用户输入密码后,程序在本地计算密码的Hash值,然后把Hash值上传到服务器;服务器将这个值与已存的Hash值对比,如果相等,则证明用户所输入的密码是正确的,验证通过;反之则验证不通过。对于一个攻击者来说, 他截获网络中传输的数据包,甚至攻破数据库,也只能得到用户密码的Hash值,由于第1个性质,攻击者很难找到另一个密码,使得其Hash值等于给定的Hash值,因此攻击者无法攻击成功。
另外,我想说明的是,Hash函数并不是一个加密算法,本身其就叫做Hash算法,作为密码学的一个原型函数。我们需要注意到,Hash函数的输入只有被Hash的消息本身,没有涉及到任何秘钥的运算,任何人都可以通过给定的消息计算Hash的结果。所以,有一些朋友在其博客里面把Hash作为一种Encryption,是一个错误的命名方法。
经典Hash函数
那么,这样的Hash函数到底存不存在呢?我们现在公认的,大家一般都会用到的Hash函数有如下几种:MD5,SHA1,SHA256,SHA512等等。有兴趣的朋友们可以参考一下JDK对于MessageDigest类中提到的,Java Cryptography Architecture API Specification & Reference中的附录 A给出的描述,就可以得到几乎所有经典Hash函数的名称了。在此我给出链接:http://docs.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html#MDEx。
清华大学王小云教授的贡献
在中国密码学界,王小云教授的名声不可谓不大。她在2005年的一项工作让世界密码学界轰动了。其论文也被收录在被认为是密码学最顶级的会议:CRYPTO中。那么,王小云教授的贡献究竟是什么呢?王小云教授指出,对于经典的MD5和SHA1,存在一种高效的算法,使得对于任意m作为输入,得到输出的结果,很快找到另一个输入m' \