概述
Hash函数(散列函数):是一种将任意长度的数据映射到有限长度的域上。通俗来讲,就是将一串任意长度的数据进行打乱混合,转换为一段固定长度的数据输出,这段数据便成为输入数据的一个“指纹”(特征)。Hash函数的首要目标是保证数据的完整性。而不是安全性。
Hash函数的安全性
Hash函数的安全需求
需求 |
描述 |
输入长度可变 |
Hash函数可以应用于任意长度的数据块 |
输出长度固定 |
Hash的输出长度是固定的 |
效率 |
对任意的x,计算H(x)在计算上是较容易的 |
抗原像攻击(单向性) |
对任意给定的H(n),计算n在计算上是不可行的。 |
抗第二原像攻击(抗弱碰撞性) |
对任意给定的x,找到一个y(y≠x)使得H(x)=H(y)在计算上不可行 |
抗碰撞攻击(抗强碰撞性) |
对任意的Hash函数,找到满足的H(x)=H(y)在计算上不可行。 |
伪随机性 |
输入相同,H的输出也一定相同 |
Hash函数的安全属性
1. Collsion-free 无冲突
根据Hash的安全需求,Hash函数的输入长度InputLength是任意的,但是,其输出长度的OutputLength是固定的。从理论上而言,Input的组合是无穷多种,而OutPut的组合是有限的,那么应该是存在两个不同的数据会生成同样的哈希值。但是,对于SHA256而言,尝试2256+1次数据会有1次数据冲突。尝试2130次数据会有99%的可能性找到冲突。
应用: 信息摘要(Message digest),因为冲突的几率很小,那么我们可以利用记住大信息的哈希值来进行信息比对,以减少数据比对的运算。也就是将哈希值作为信息的识别“指纹”。
2.Hiding 隐藏性
Hash函数的单项函数,是不可逆的,Hash值不能转换为原来的数据值,能够很好的隐藏原数据。对于一个大的数据库而言,如身份认证,一个公司存储的用户账号密码,一般存储其登录账号和密码的Hash值,避免数据泄露后,攻击者能够轻松的使用用户账户。但是,如果数据是由简单的数字组成,那么也很容易遭受到暴力破解,这也是为什么在密码设定中会要求用户加入字母,符号等。为了达到隐藏元数据的目的,元数据需要选自范围特别广的集(highmin-entropy)
应用: Commitment,即只公布哈希值,而在之后再公布哈希前的原数据。后期所有用户都可以通过比对哈希值来验证“信封”中的内容是否更改。
3.Puzzle-friendly 谜题友好性
Hash函数中一个字节的变动就能导致生成完全不同的哈希值(雪崩效应),且哈希值的改变没有任何的规律可循。
对于每一个用k来加密x得到的结果H(k | x) = y,在知道y、k和H(k|x)的条件下,不存在比随机遍历更好的方法。
Hash函数的应用
消息认证
消息认证是用来验证消息完整性的一种机制或服务。消息认证确保收到的数据和发送时是一致的(消息没有被篡改)。
消息认证的本质是:利用Hash函数对发送者即将发送的消息计算一组Hash值,然后将消息与Hash值一同发送。接收者在收到消息后利用相同的Hash函数对消息进行计算,并将结果与发送过来的Hash值进行比对,若不匹配,则推断出消息在传送的过程中受到了篡改。
消息认证共有一下几种不同的方法:
1.使用对称加密消息和Hash码。
2.使用堆成密码算法支队Hash码进行加密。
3.不使用加密算法,即假设通信双方之前已经共享了一个秘密值,将该秘密值和消息串联起来再进行Hash,再将Hash过后的值与消息进行拼接发送。
4.在步骤3的基础之上,将消息和拼接Hash过后的Hash值一起对称加密发送。
数字签名
数字签名实质上也是利用Hash函数对消息进行杂糅,但不同于消息认证的是,他将这串数据或者数据的一部分进行密码变换。数字签名能够在保证数据的完整性的同时,还能够保证数据发送方的不可抵赖性。
基于公钥密码体制和私钥密码体制都能够得到数字签名,但主要是基于公钥密码体制的数字签名(这句话源自百度)。个人理解是在对称秘钥的情境下,这种签名又叫消息认证码。常用的数字签名的算法有:RSA、ElGamal、Des/DSA,椭圆曲线数字签名算法。
Hash码用于数字签名的方案:
- 使用用户的私钥,利用公钥密码算法对Hash值进行加密。
- 上一种方法没有提供保密性,所以可以在上述的过程之后,利用对称密码进行加密。
SHA
SHA其实只是Secure Hash Algorithm(安全Hash算法)的缩写。事实上,其余被广泛使用的Hash函数被先后显现存在安全性问题。如:2004年的国际密码讨论年会(CRYPTO)尾声,王小云及其研究同事展示了MD5、SHA-0及其他相关散列函数的散列冲撞。也就是说,他们找到了一种方法,能够让x≠y的情况下MD5(x)=MD5(y),并且这种方法代价远小于随机暴力破解。其实,SHA-1也已经被找到了方法能够散列冲撞。
所以我们主要讨论SHA-2,而SHA-2中一共有多种版本,其Hash值得长度依次为224、256、384和512位,人们一般将其称为:SHA-224、SHA-256、SHA-384和SHA-512。SHA-2其实和SHA-1类似,都采用的是相同得迭代与二元逻辑操作,SHA-1和SHA-2之间的主要区别在于哈希的长度。SHA-1的散列是更基础的版本,提供了较短的代码,唯一组合的可能性较小,而SHA-2或SHA-256创建的散列则更长,因此更为复杂。
SHA参数对比
|
SHA-1 |
SHA-224 |
SHA-256 |
SHA-384 |
SHA-512 |
消息摘要长度 |
160 |
224 |
256 |
384 |
512 |
消息长度 |
<264
|
<264
|
<264
|
<2128
|
<2128
|
分组长度 |
512 |
512 |
512 |
1024 |
1024 |
字长度 |
32 |
32 |
32 |
64 |
64 |
步骤数 |
80 |
64 |
64 |
80 |
80 |
SHA-512
Input: m(m<2128)
Output: 512bit
处理单元:1024bit
-
附件填充位: 填充m,使得填充后的 length(message)≡ 896 (mod 1024 )。
填充要求:即便已经满足 length(message)≡ 896 (mod 1024 ),也要对消息进行填充一次。
填充方式:填充由一个1,后全由0补充。
-
附加长度:在消息后附加一个128位的块。在message 后面加128位的数据块, 他表示了m的长度。
由①②可知,填充后的信息M已经是1024整数倍了,将M分为一个个的函数处理单元,M1,M2,…,MN。
- 初始化Hash。Hash的中间结果与最中结果都存在寄存器中。缓冲区由8个64位寄存器组成(a,b,c,d,e,f,g,h)。这8个寄存器的初始值为:前8个个素数取平方根,取小数部分前64位。(以高位存储)
- 以1024位为分组处理数据,SHA-512需要经过80轮运算模块(SHA-256经过64轮)
- 输出