散列函数的应用及其安全性
一、散列函数的具体应用
Hash(散列函数),一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。由于散列函数的应用的多样性,它们经常是专为某一应用而设计的。正确的应用场景:
1,数据校验
HASH函数有类似数据冗余校验类似的功能,但是它比简单的冗余校验碰撞的概率要小得多,顾而在现在密码学中总是用HASH来做关键数据的验证。
2,单向性的运用
利用HASH函数的这个特点,我们能够实现口令,密码等安全数据的安全存储。密码等很多关键数据我们需要在数据库中存储,但是在实际运用的过程中,只是作比较操作,顾而我们可以比较HASH结 果。这一点相信在银行等系统中有所运用,否则我们真的要睡不着觉了:)
3,碰撞约束以及有限固定摘要长度
数字签名正是运用了这些特点来提高效率的。我们知道非对称加密算法速度较低,通过HASH处理我们可以使其仅仅作用于HASH摘要上,从而提高效率。
4,可以运用HASH到随机数的生成和密码,salt值等的衍生中
因为HASH算法能够最大限度的保证其唯一性,故而可以运用到关键数据的衍生中(从一个随机的种子数产生,并且不暴露种子本身秘密)。
二、散列函数的安全性以及目前安全散列函数的发展
(1)散列函数的安全性
1、已知哈希函数的输出,要求它的输入是困难的,即已知c=Hash(m),求m是困难的。这表明函数应该具有单向性。
2、已知m,计算Hash(m)是容易的。这表明函数应该具有快速性。
3、已知,构造m2使Hash(m2)=c1是困难的。这表明函数应该具有抗碰撞性。
4、c=Hash(m),c的每一比特都与m的每一比特有关,并有高度敏感性。即每改变m的一比特,都将对c产生明显影响。这表明函数应该具有雪崩性。
5、作为一种数字签名,还要求哈希函数除了信息m自身之外,应该基于发信方的秘密信息对信息m进行确认。
6、接受的输入m数据没有长度限制;对输入任何长度的m数据能够生成该输入报文固定长度的输出。
有两种方法可以攻击安全散列函数:密码分析法和暴力攻击法。
密码分析法:
(1)唯密文攻击(Ciphertext—only attack)。
攻击者手中除了截获的密文外,没有其他任何辅助信息。唯密文攻击是最常见的一种密码分析类型,也是难度最大的一种。
(2)已知明文攻击( Known – plaintext
attack)。
攻击者除了掌握密文,还掌握了部分明文和密文的对应关系。举例来看,如果是遵从通信协议的对话,由于协议中使用固定的关键字,如“login”“password”等,通过分析可以确定这关键字对应的密文。如果传输的是法律文件、单位通知等类型的公文,由于大部分公文有固定的格式和一些约定的文字,在截获的公文较多的条件下,可以推测出一些文字、词组对应的密文。
(3)选择明文攻击( Chosen – plaintext
attack)。
攻击者知道加密算法,同时能够选择明文并得到相应明文所对应的密文。这是比较常见的一种密玛分析类型。例如,攻击者截获了有价值的密文,并获取了加密使用设备,向设备中输入任意明文可以得到对应的密文,以此为基础,攻击者尝试对有价值的密文进行破解。选择明文攻击常常被用于破解采用公开密钥密码系统加密的信息内容。
(4)选择密文攻击( Chosen –
ciphertext attack)。
攻击者知道加密算法,同时可以选择密文并得到对应的明文。采用选择密文攻击这种攻击方式,攻击者的攻击目标通常是加密过程使用的密钥。基于公开密钥密码系统的数字签名,容易受到这种类型的攻击。
·生日悖论(Birthday paradox):
生日悖论是指,如果一个房间里有23个或23个以上的人,那么至少有两个人的生日相同的概率要大于50%。这就意味着在一个典型的标准小学班级(30人)中,存在两人生日相同的可能性更高。对于60或者更多的人,这种概率要大于99%。从引起逻辑矛盾的角度来说生日悖论并不是一种悖论,从这个数学事实与一般直觉相抵触的意义上,它才称得上是一个悖论。大多数人会认为,23人中有2人生日相同的概率应该远远小于50%。
·生日攻击原理:
由此我们可以将它用在碰撞,得到不同Message有着相同tag。
假设:取样次数为N,M:M1-Mn,取值在tag:1-B中,并且假设分布随机均匀相互独立。
取样次数n与B的关系,n=1.2*B^0.5(这是生日悖论中最坏的情况。)
证明:M2不等于M1的概率为(B-1)/B,同理可得M3为(B-2)/B,M4为(B-3)/B...Mn为(B-n+1)/B。
因此,其中有碰撞的概率为:1-(1-1/B)(1-2/B).....(1-(k-1)/B)>= (1-e)^(-n^2/2B)
因为n=1.2*B^0.5,因此(1-e)^(-n^2/2B)=1-e^-0.72=0.53>50%
结论,因此使用生日攻击,我们只需2^(n/2)次寻找,就有50%概率能找到相同tag的两个不同Message。
这其实便是利用了穷举法。穷举攻击法的破解思路是尝试所有的可能以找出明文或者密钥。穷举攻击法可以划分为穷举密钥和穷举明文两类。穷举密钥是指攻击者依次使用各种可能的解密密钥对截收的密文,进行试译,如果某个解密密钥能够产生有意义的明文,则判断相应的密钥就是正确的解密密钥。穷举明文是指攻击者在保持加密密钥不变的条件下,对所有可能的明文进行加密,如果某段明文加密的结果与截获的密文一致,则判断相应的明文就是发送者发送的信息。
散列函数抵抗暴力攻击的强度完全依赖于算法生成的散列码长度。目前常用的HASH函数主要有两个系列,MD 和 SHA系列。MD系列主要包括 MD2,MD4,MD5,Van Oorschot和Wiener曾经提出,花费1000万美元涉及一个被专门用来搜索MD5算法碰撞的机器,则平均24天内就可以找到一个碰撞。不幸的是这一系列的hash函数都已经被证实是不够安全的了,我国山东大学教授王晓云就是因为在有限的时间内成功地破解了MD2和MD5算法而扬名海内外,SHA系列正是因此而生。近些年,应用最广泛的散列函数是SHA。由于其他每一种被广泛应用的散列函数都已经被证实存在这密码分析学中的缺陷,接着到2005年,SHA或许仅存的安全散列算法。SHA由美国国家标准与技术研究院(NIST)开发。
(2)目前安全散列函数的发展
1997年Bob Jenkins 在Dr. Dobbs 的期刊上发表了一篇关于hash函数的文章:A hash function for hash Table lookup。在这篇文章中,Bob广泛的归类了已存的hash函数,并提出了自己的”lookup2”。随后他又在2006年发布了lookup3 ,可以说这是第一个“现代”的hash函数,从某种意义上来说它不仅快速(0.5bytyes/cycle according to Bob)而且没有任何严重缺陷。
2008年Austin Appleby 发表了一个新的称作“MurmurHash”的hash 函数。在它最近的版本中其hash速度大约是lookup3的2倍(大约1byte/cycle),并且同时有32-bit和64-bit两个版本。32-bit版的只使用32-bit公式并输出32-bit的hash,64-bit版的使用64-bit公式产出64-bit的hash。跟据Austin的分析该函数拥有优秀的特性,然而Bob Jenkins在DR.Dobbs上发表的扩充文章说:我能看到[MurmurHash]比我的lookup3差,但是我不知道差多少,我没有测试。由于优秀的速度和统计特性,MurmurHash很快就变的流行起来。
2011年两个基于MurmurHash的改进函数发表,这两个函数都是在指令级别的并行性上对MurmurHash进行了加强。Google发布了CityHash(written by Geoff Pike and Jyrki Alakuijala),Bob Jenkins 发布了自己的SpookyHash。两个函数都是原MurmurHash速度的2x,但两个函数都使用了64-bit的公式,而没有32-bit的版本。CityHash依赖于CRC32指令集,该指令出现在SSE 4.2(Intel Nehalem及以后)。SpookyHash产生128位的输出,而CityHash有64-bit,128-bit和256-bit可选。
MD5 和 SHA1 是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。MD4(RFC 1320)是 MIT 的Ronald L. Rivest在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32位操作数的位操作来实现的。
MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。
SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于2^64位的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。
三、MD5算法在验证软件完整性时可能出现的问题
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5算法的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等。
MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
MD5算法可以被用来验证文件的完整性和是否被篡改,通过对任意长度的信息逐位进行计算,产生一个二进制长度为128位(十六进制长度就是32位)的 hash 值, 不同的文件产生相同的hash的可能性是非常小的。MD5在实际应用中通常有两种用法,一种是计算一个字符串的MD5值,常用于密码相关的操作;另一种是用于计算一个文件的MD5值,一般用于网络传输中验证文件是否出错。具体应用体现在以下三个方面:
1、一致性验证
MD5的典型应用是对一段文本信息产生信息摘要,以防止被篡改。常常在某些软件下载站点的某软件信息中看到其MD5值,它的作用就在于我们可以在下载该软件后,对下载回来的文件用专门的软件(如Windows
MD5 Check等)做一次MD5校验,以确保我们获得的文件与该站点提供的文件为同一文件。
2、数字证书
如果有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。
3、安全访问认证
在Unix系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。
但是,在使用MD5算法来验证完整性时,由于MD5算法是公开的,所有人都可以获得和使用MD5算法,那就意味着别人可以利用相同的算法针对你的加密值不断地进行计算。如果不对MD5算法进行一些处理,那么当我们将自己的重要接口暴露在互联网上的时候,比如登陆接口,攻击者就可以同样利用MD5加密算法对我们进行撞库攻击和关键信息比对。为了避免这个问题,我们可以给算法增加一个偏移量,比如在原始数据上拼接一段数据在进行加密;或者根据原始数据分布范围进行转换,用得到的新值进行MD5计算,这样子被破解的风险就会大大降低。