定义
HashHashHash,一般译作散列、哈希,就是能把任意长度的输入(又做预映射)通过散列算法,变换成固定长度的输出,这个输出就是散列值。
散列值通常是数字和字母的组合。
性质
1、不可逆性。已知哈希函数FFF和xxx哈希值,无法逆向求出xxx.
2、对于特定的哈希函数,只要输入不变,那么散列值也肯定是唯一不变的.
3、哈希函数产生的映射应当保持均匀,即不要使得映射结果堆积在小区间的某一区域.
4、敏感性。哪怕输入数据只改变1bit1bit1bit,得到的哈希值也大不相同.
5、抗碰撞性。理想HashHashHash函数是无碰撞的,但实际很难做到这一点。有两种抗碰撞性:弱抗碰撞性、强抗碰撞性.
典型的哈希函数
常见的HashHashHash算法有MD5MD5MD5和SHASHASHA系列,目前MD5MD5MD5和SHA1SHA1SHA1已被破解,一般推荐使用SHA2−256SHA2-256SHA2−256算法.
MD5
输入任意长度的信息,以**512bit512bit512bit输入数据块**为单位,输出为128bit128bit128bit的信息(数字指纹)。
实现过程
1、补位。使输入信息的长度变为(N∗512+448)bit(N*512+448)bit(N∗512+448)bit,补位内容为100...0100...0100...0
那为什么不补为512bit512bit512bit的整数倍呢?其实剩余64bit64bit64bit是原始信息的长度。也就是说,补位最终结果是N∗512bitN*512bitN∗512bit的.
需要注意的是,补位操作必须进行,即使最初信息的长度已经满足(N∗512+448)bit(N*512+448)bit(N∗512+448)bit,但还是要加上512bit512bit512bit,然后再补64bit64bit64bit记录原始
信息长度. 如下图:
2、分割。把结果分为n组,每一组长度为512bit512bit512bit.
3、计算。
∙\bullet∙ 准备四个标准幻数,每一个数4个字节,总的16字节。其实四个幻数的值定义也很直接,就是32个16进制字面值依次排列。
分别是:
A=01234567A = 01234567A=01234567 B=89ABCDEFB = 89ABCDEFB=89ABCDEF C=FEDCBA98C = FEDCBA98C=FEDCBA98 D=76543210D = 76543210D=76543210
那么,这四个幻数是用来做什么的呢?
其实不难发现,四个幻数的长度和MD5MD5MD5散列值的长度都是128bit128bit128bit,四个幻数就是用来做循环初始计算值的。
最终MD5MD5MD5散列值就是四个标准幻数经过多轮哈希运算的结果。
需要注意,在程序中,幻数是用小端字节表示的,即
A=0x67452301A = 0x67452301A=0x67452301 B=0xEFCDAB89B = 0xEFCDAB89B=0xEFCDAB89 C=0x98BACDFEC = 0x98BACDFEC=0x98BACDFE D=0x10325476D = 0x10325476D=0x10325476
准备工作完成,就可以开始计算了。
∙\bullet∙ 数据被分为n个512bit512bit512bit,也就是n个64字节,再把每一个64字节分成16份,每份四个字节。
∙\bullet∙ 定义四个函数,分别是
FF(A,B,C,D,X,S,AC)
FF(A,B,C,D,X,S,AC)
FF(A,B,C,D,X,S,AC)
GG(A,B,C,D,X,S,AC) GG(A,B,C,D,X,S,AC) GG(A,B,C,D,X,S,AC)
HH(A,B,C,D,X,S,AC) HH(A,B,C,D,X,S,AC) HH(A,B,C,D,X,S,AC)
II(A,B,C,D,X,S,AC) II(A,B,C,D,X,S,AC) II(A,B,C,D,X,S,AC)
前四个参数分别对应四个标准幻数,第五个参数是每一小份的四个字节数据,第六个和第七个参数都是一些固定常数,执行一些逻辑与、或、非、异或运算,加法运算和移位运算。
∙\bullet∙ 将四个标准幻数换着顺序作为前四个参数输入,并将16份4字节数据依次作为第五个参数代入,经过这么一轮运算,四个标准幻数的值就变了。
∙\bullet∙ 将四个标准幻数与一开始的值相加,得到更新后的四个幻数结果。这样就处理完了一个64字节的数据。
∙\bullet∙ 四个更新后的标准幻数作为第二轮的四个标准幻数输入,并且载入第二个64字节数据中进行运算。
∙\bullet∙ 重复上述过程,直到n个64字节数据全部计算完成,最终得到的四个标准幻数用十六进制显示出来就是最终MD5MD5MD5的散列值。
SHA1(Secure Hash Algorithm)
对于长度小于264bit2^{64}bit264bit的消息,将输入流按照每块512b(64B)512b(64B)512b(64B)进行分块,并产生160b(20B)160b(20B)160b(20B)的信息摘要。
实现过程
大致框图:
1、补位。(与MD5MD5MD5补位是一样的)
第一位:补1
其余位:补0
直至满足 L mod 512 = 448
512 - 448 = 64
剩余64bit是初始消息的长度
eg:
2、将信息分为nnn个512bit512bit512bit。
3、每个512b512b512b的运算。
∙\bullet∙ 把512b512b512b分为262626份32b32b32b,将161616份扩充到808080份.
那么,如何扩充呢?
Wt={Mti 0⩽t⩽15ROTL1(Wt−3⨁Wt−8⨁Wt−14⨁Wt−16) 16⩽t⩽79
W_{t}=\left\{\begin{matrix}
M_{t}^{i}\textbf{ }\textbf{ }0\leqslant t\leqslant15\\
ROTL^{1}(W_{t-3}\bigoplus W_{t-8}\bigoplus W_{t-14}\bigoplus W_{t-16})\textbf{ }\textbf{ }16\leqslant t\leqslant79
\end{matrix}\right.
Wt={Mti 0⩽t⩽15ROTL1(Wt−3⨁Wt−8⨁Wt−14⨁Wt−16) 16⩽t⩽79
ROTL1ROTL^{1}ROTL1表示左移一位.
eg:
W16=(W13⨁W8⨁W2⨁W0)<<1
W_{16}=(W_{13}\bigoplus W_{8}\bigoplus W_{2}\bigoplus W_{0})<<1
W16=(W13⨁W8⨁W2⨁W0)<<1
∙\bullet∙ 设置555个初始量,
H0(0)=67452301
H_{0}^{(0)}=67452301
H0(0)=67452301
H1(0)=efcdab89 H_{1}^{(0)}=efcdab89 H1(0)=efcdab89
H2(0)=98badcfe H_{2}^{(0)}=98badcfe H2(0)=98badcfe
H3(0)=10325476 H_{3}^{(0)}=10325476 H3(0)=10325476
H4(0)=c3d2e1f0 H_{4}^{(0)}=c3d2e1f0 H4(0)=c3d2e1f0
∙\bullet∙ 将初始量的值分别赋给a,b,c,d,ea,b,c,d,ea,b,c,d,e
a=H0(0)
a=H_{0}^{(0)}
a=H0(0)
b=H1(0) b=H_{1}^{(0)} b=H1(0)
c=H2(0) c= H_{2}^{(0)} c=H2(0)
d=H3(0) d = H_{3}^{(0)} d=H3(0)
e=H4(0) e = H_{4}^{(0)} e=H4(0)
∙\bullet∙ 进行808080轮运算.
for t=0 to 79:for \textbf{ }t = 0 \textbf{ }to\textbf{ } 79:for t=0 to 79:
{
\left \{ \right.
{
T=ROTL5(a)+ft(b,c,d)+e+Kt+WtT = ROTL^{5}(a)+f_{t}(b,c,d)+e+K_{t}+W_{t}T=ROTL5(a)+ft(b,c,d)+e+Kt+Wt
e=de=de=d
d=cd=cd=c
c=ROLT30(b)c=ROLT^{30}(b)c=ROLT30(b)
b=ab = ab=a
a=Ta=Ta=T
}
\left. \right \}
}
其中,
Kt={5a827999 0⩽t⩽196ed9eba1 20⩽t⩽398f1bbcdc 40⩽t⩽59ca62c1d6 60⩽t⩽79
K_{t}=\left\{\begin{matrix}
5a827999\textbf{ }\textbf{ }0\leqslant t\leqslant19\\
6ed9eba1\textbf{ }\textbf{ }20\leqslant t\leqslant39\\
8f1bbcdc\textbf{ }\textbf{ }40\leqslant t\leqslant59\\
ca62c1d6\textbf{ }\textbf{ }60\leqslant t\leqslant79
\end{matrix}\right.
Kt=⎩⎪⎪⎨⎪⎪⎧5a827999 0⩽t⩽196ed9eba1 20⩽t⩽398f1bbcdc 40⩽t⩽59ca62c1d6 60⩽t⩽79
ft(x,y,z)={Ch(x,y,z)=(x∧y)⨁(x∧z), 0⩽t⩽19Parity(x,y,z)=x⨁y⨁z, 20⩽t⩽39Maj(x,y,z)=(x∧y)⨁(x∧z)⨁(y∧z), 40⩽t⩽59Parity(x,y,z)=x⨁y⨁z, 60⩽t⩽79 f_{t}(x,y,z)=\left\{\begin{matrix} Ch(x,y,z)=(x\wedge y)\bigoplus(x\wedge z),\textbf{ }\textbf{ }0\leqslant t\leqslant19\\ Parity(x,y,z)=x\bigoplus y\bigoplus z,\textbf{ }\textbf{ }20\leqslant t\leqslant39\\ Maj(x,y,z)=(x\wedge y)\bigoplus(x\wedge z)\bigoplus(y\wedge z),\textbf{ }\textbf{ }40\leqslant t\leqslant59\\ Parity(x,y,z)=x\bigoplus y\bigoplus z,\textbf{ }\textbf{ }60\leqslant t\leqslant79 \end{matrix}\right. ft(x,y,z)=⎩⎪⎪⎨⎪⎪⎧Ch(x,y,z)=(x∧y)⨁(x∧z), 0⩽t⩽19Parity(x,y,z)=x⨁y⨁z, 20⩽t⩽39Maj(x,y,z)=(x∧y)⨁(x∧z)⨁(y∧z), 40⩽t⩽59Parity(x,y,z)=x⨁y⨁z, 60⩽t⩽79
∙\bullet∙ 将808080轮运算之后得到的a,b,c,d,ea,b,c,d,ea,b,c,d,e分别与初始量相加.
∙\bullet∙ 将上述结果作为第二个512b512b512b的初始量进行循环计算。
∙\bullet∙ 重复上述过程,直到nnn个512b512b512b数据全部计算完成,最终得到的a,b,c,d,ea,b,c,d,ea,b,c,d,e就是SHA1SHA1SHA1的最终结果。