算法学习|SHA 算法描述与实现

SHA 算法的原理及实现
章节目录

  1. 简介
  2. 算法描述
    2.1 数据准备
    2.1.1 数据填充
    2.1.2 数据分块
    2.1.3 设置初始 Hash 值
    2.2 Hash 计算
    2.2.1 SHA-1
    2.2.2 SHA-256
    2.2.3 SHA-512
  3. 实现
作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!
简介## SHA 算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
本文我们将介绍以下 SHA 算法: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256.
其中 SHA-224 和 SHA-256 使用相同的算法, 区别在于初始 Hash 值不同, 最终结果只使用算法输出的数据中的前224/256 bit.
SHA-384, SHA-512, SHA-512/224, SHA-512/256 使用相同的算法, 区别在于初始 Hash 值不同, 最终结果只使用算法输出的数据中的前384/512/224/256 bit.
而 SHA-2* 和 SHA-384,SHA-5* 算法也非常类似, 区别在于采用的字(Word) 长度不同, SHA-2*使用 32-bit 的字, 而 其他算法使用 64-bit 的字. 算法的迭代次数也不一样.
算法描述## 本文中将介绍的 SHA 算法的计算步骤从大体上可以分为两步: 数据准备Hash 计算.
数据准备###
在数据准备阶段, 我们也像 MD5 那样, 需要先将数据填充到特定长度,同时将原始数据长度填充进去,然后对数据进行分块, 因为我们的算法是基于块进行的. SHA 家族中的具体算法的实现大体相同, 只是填充长度的bit数,分块大小略有不同而已.
在数据准备阶段我们需要进行三个操作: 数据填充, 数据分块, 设置初始 Hash 值.
数据填充#### 我们使用M M M 表示数据数据, 它的长度使用l l l 表示.
对于算法 SHA-1, SHA-224, SHA-256, 数据填充方法如下:
先填充 1 bit 的 ‘1’ 到数据末尾, 然后紧接着填充 k 个 ‘0’, 这里 k 需要时最小的非负数且满足l + 1 + k ≡ 448 m o d 512 l+1+k\equiv448mod512 l+1+k≡448mod512, 也即是说需要将原始数据长度填充到差64位就是512的整数倍.
上述操作结束后, 将l l l 表示为 64 bit 的bit数组填充到上述步骤所得的数据之后, 此时我们得到一个长度为512整数倍的数据.
举个例子:
假设我们的数据数据为"abc", 它的长度为24(bit). 我们通过计算得到 k 应该是 423(448 - 1 - 24). 此时填充之后的数据应该如下:
01100001 ? a 01100010 ? b 01100011 ? c 1 00...00 ? 423 00...0 11000 ? t = 24 ? 64 \underbrace{01100001}_{a}\quad \underbrace{01100010}_{b}\quad \underbrace{01100011}_{c}\quad 1 \quad \overbrace{00...00}^{423}\quad \overbrace{00...0\underbrace{11000}_{t=24}}^{64} a01100001??b01100010??c01100011??100...0042300...0t=2411000???64?
填充完成之后的长度是512(bit).
对于算法 SHA-384, SHA-512, SHA-512/224, SHA-512/256, 数据填充方法如下:
先填充 1 bit 的 ‘1’ 到数据末尾, 然后紧接着填充 k 个 ‘0’, 这里 k 需要时最小的非负数且满足l + 1 + k ≡ 896 m o d 1024 l+1+k\equiv896mod1024 l+1+k≡896mod1024, 也即是说需要将原始数据长度填充到差128位就是1024的整数倍.
上述操作结束后, 将l l l 表示为 128 bit 的bit数组填充到上述步骤所得的数据之后, 此时我们得到一个长度为1024整数倍的数据.
以上述的例子为例:
假设我们的数据数据为"abc", 它的长度为24(bit). 我们通过计算得到 k 应该是 871(896 - 1 - 24). 此时填充之后的数据应该如下:
01100001 ? a 01100010 ? b 01100011 ? c 1 00...00 ? 871 00...0 11000 ? t = 24 ? 128 \underbrace{01100001}_{a}\quad \underbrace{01100010}_{b}\quad \underbrace{01100011}_{c}\quad 1 \quad \overbrace{00...00}^{871}\quad \overbrace{00...0\underbrace{11000}_{t=24}}^{128} a01100001??b01100010??c01100011??100...0087100...0t=2411000???128?
填充完成之后的长度是1024(bit).
数据分块#### 填充后的数据需要被分块.
对于算法 SHA-1, SHA-224, SHA-256,
我们将数据分为N N N 个 521-bit 的块, 分别表示为
M ( 1 ) , M ( 2 ) , . . . , M ( N ) M^{(1)}, M^{(2)}, ..., M^{(N)} M(1),M(2),...,M(N)
512-bit 的块又可以被划分为 16 个字(32-bit Word), 分别表示为
M 0 ( i ) , M 1 ( i ) , . . . , M 15 ( i ) M^{(i)}_{0}, M^{(i)}_{1}, ..., M^{(i)}_{15} M0(i)?,M1(i)?,...,M15(i)?
对于算法 SHA-384, SHA-512, SHA-512/224, SHA-512/256
我们将数据分为N N N 个 1024-bit 的块, 分别表示为
M ( 1 ) , M ( 2 ) , . . . , M ( N ) M^{(1)}, M^{(2)}, ..., M^{(N)} M(1),M(2),...,M(N)
1024-bit 的块又可以被划分为 16 个字(64-bit Word), 分别表示为
M 0 ( i ) , M 1 ( i ) , . . . , M 15 ( i ) M^{(i)}_{0}, M^{(i)}_{1}, ..., M^{(i)}_{15} M0(i)?,M1(i)?,...,M15(i)?
设置初始 Hash 值#### 每个特定的 SHA 算法, 都有相应的初始 Hash 值. 在计算 Hash 之前, 我们需要先将初始值准备好.
为了减少文章篇幅, 这里我们不列出这些初始值和 Hash 计算过程中使用到的常量 K K K,后边算法实现中会给出相应数据.
Hash 计算###
SHA-1#### SHA-1 算法要求输入数据的长度不能大于2 6 4 2^64 264, 最小长度为0.
伪代码如下:
【算法学习|SHA 算法描述与实现】 R O T L n ( x ) = ( x < < n ) ∪ ( x > > w ? n ) ROTL^n(x)=(x < < n) \cup (x > > w - n) ROTLn(x)=(x<>w?n)
f t ( x , y , z ) f_t(x,y,z) ft?(x,y,z) ={ C h ( x , y , z ) = ( x ∩ y ) ? ( ? x ∩ z ) , 0 ≤ t ≤ 19 P a r i t y ( x , y , z ) = x ? y ? z , 20 ≤ t ≤ 39 M a j ( x , y , z ) = ( x ∩ y ) ? ( x ∩ z ) ? ( y ∩ z ) , 40 ≤ t ≤ 59 P a r i t y ( x , y , z ) = x ? y ? z , 60 ≤ t ≤ 79 \begin{cases} Ch(x,y,z)=(x\cap y)\bigoplus (?x\cap z), \qquad 0\leq t\leq19\\ \quad \\ Parity(x,y,z)=x\bigoplus y\bigoplus z, \qquad 20\leq t\leq39\\ \quad \\ Maj(x,y,z)=(x\cap y)\bigoplus (x\cap z)\bigoplus (y\cap z), \qquad 40\leq t\leq59\\ \quad \\ Parity(x,y,z)=x\bigoplus y\bigoplus z, \qquad 60\leq t\leq79\\ \quad \\ \end{cases} ??????????????????????????????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?
For i=1 to N:
{
//1. 计算W t W_t Wt?
W t \quad W_t Wt? ={ M t ( 0 ) , 0 ≤ t ≤ 15 R O T L 1 ( W t ? 3 ? W t ? 8 ? W t ? 14 ? W t ? 16 ) , 16 ≤ t ≤ 79 \begin{cases} M^{(0)}_t, \qquad 0\leq t\leq15\\ \quad \\ ROTL^1(W_{t-3}\bigoplus W_{t-8}\bigoplus W_{t-14}\bigoplus W_{t-16}), \qquad 16\leq t\leq79\\ \end{cases} ??????Mt(0)?,0≤t≤15ROTL1(Wt?3??Wt?8??Wt?14??Wt?16?),16≤t≤79?
//2. 初始化工作变量 a, b, c, d, e. 他们用来存储在第 i-1 次迭代式的 Hash 值
// 他们的初始值就是我们在"设置初始 Hash 值"小节中所说的值.
a = H 0 i ? 1 b = H 1 i ? 1 c = H 2 i ? 1 d = H 3 i ? 1 e = H 4 i ? 1 \quad a=H^{i-1}_0 \\ \quad b=H^{i-1}_1 \\ \quad c=H^{i-1}_2 \\ \quad d=H^{i-1}_3 \\ \quad e=H^{i-1}_4 \\ a=H0i?1?b=H1i?1?c=H2i?1?d=H3i?1?e=H4i?1?
// 3
For t=0 to 79:
{
T = R O T L 5 ( a ) + f t ( b , c , d ) + e + K t + W t e = d d = c c = R O T L 3 0 ( b ) b = a a = T \qquad T=ROTL^5(a)+f_t(b,c,d)+e+K_t+W_t \\ \qquad e=d \\ \qquad d=c \\ \qquad c=ROTL^30(b) \\ \qquad b=a \\ \qquad a=T \\ T=ROTL5(a)+ft?(b,c,d)+e+Kt?+Wt?e=dd=cc=ROTL30(b)b=aa=T
}
//4. 计算第i t h i^{th} ith 中间 hash 值 H i H^i Hi
H 0 ( i ) = a + H 0 ( i ? 1 ) H 1 ( i ) = b + H 1 ( i ? 1 ) H 2 ( i ) = c + H 2 ( i ? 1 ) H 3 ( i ) = d + H 3 ( i ? 1 ) H 4 ( i ) = e + H 4 ( i ? 1 ) \quad H^{(i)}_0=a+H^{(i-1)}_0 \\ \quad H^{(i)}_1=b+H^{(i-1)}_1 \\ \quad H^{(i)}_2=c+H^{(i-1)}_2 \\ \quad H^{(i)}_3=d+H^{(i-1)}_3 \\ \quad H^{(i)}_4=e+H^{(i-1)}_4 \\ H0(i)?=a+H0(i?1)?H1(i)?=b+H1(i?1)?H2(i)?=c+H2(i?1)?H3(i)?=d+H3(i?1)?H4(i)?=e+H4(i?1)?
}
在经过 N 次迭代之后, 最终结果为H 0 ( N ) , H 1 ( N ) , H 2 ( N ) , H 3 ( N ) , H 4 ( N ) H^{(N)}_0, H^{(N)}_1, H^{(N)}_2, H^{(N)}_3, H^{(N)}_4 H0(N)?,H1(N)?,H2(N)?,H3(N)?,H4(N)? 的字节表示依次连接所组成的字节数组.
SHA-256#### SHA-256 算法要求输入数据的长度不能大于2 6 4 2^64 264, 最小长度为0.
SHA-224 算法的计算过程与 SHA-256 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-224 算法的最终结果是取 SHA-256 算法结果的前 224 bit.
伪代码如下:
S H R n ( x ) = x > > n SHR^n(x)=x > > n SHRn(x)=x>>n
R O T R n ( x ) = ( x > > n ) ∪ ( x < < w ? n ) ROTR^n(x)=(x > > n)\cup (x < < w - n) ROTRn(x)=(x>>n)∪(x<Σ 0 { 256 } ( x ) = R O T R 2 ( x ) ? R O T R 13 ( x ) ? R O T R 22 ( x ) \Sigma^{\{256\}}_0(x)=ROTR^2(x)\bigoplus ROTR^{13}(x)\bigoplus ROTR^{22}(x) Σ0{256}?(x)=ROTR2(x)?ROTR13(x)?ROTR22(x)
Σ 1 { 256 } ( x ) = R O T R 6 ( x ) ? R O T R 11 ( x ) ? R O T R 25 ( x ) \Sigma^{\{256\}}_1(x)=ROTR^6(x)\bigoplus ROTR^{11}(x)\bigoplus ROTR^{25}(x) Σ1{256}?(x)=ROTR6(x)?ROTR11(x)?ROTR25(x)
σ 0 { 256 } ( x ) = R O T R 7 ( x ) ? R O T R 18 ( x ) ? S H R 3 ( x ) \sigma^{\{256\}}_0(x)=ROTR^7(x)\bigoplus ROTR^{18}(x)\bigoplus SHR^3(x) σ0{256}?(x)=ROTR7(x)?ROTR18(x)?SHR3(x)
σ 1 { 256 } ( x ) = R O T R 17 ( x ) ? R O T R 19 ( x ) ? S H R 10 ( x ) \sigma^{\{256\}}_1(x)=ROTR^{17}(x)\bigoplus ROTR^{19}(x)\bigoplus SHR^{10}(x) σ1{256}?(x)=ROTR17(x)?ROTR19(x)?SHR10(x)
For i=1 to N:
{
//1. 计算W t W_t Wt?
W t \quad W_t Wt? ={ M t ( 0 ) , 0 ≤ t ≤ 15 σ 1 { 256 } ( W t ? 2 ) + W t ? 7 + σ 0 { 256 } ( W t ? 15 ) + W t ? 16 , 16 ≤ t ≤ 63 \begin{cases} M^{(0)}_t, \qquad 0\leq t\leq15\\ \quad \\ \sigma^{\{256\}}_1(W_{t-2})+W_{t-7}+\sigma^{\{256\}}_0(W_{t-15})+W_{t-16}, \qquad 16\leq t\leq63\\ \end{cases} ??????Mt(0)?,0≤t≤15σ1{256}?(Wt?2?)+Wt?7?+σ0{256}?(Wt?15?)+Wt?16?,16≤t≤63?
//2. 初始化工作变量 a, b, c, d, e, f, g, h. 他们用来存储在第 i-1 次迭代式的 Hash 值
// 他们的初始值就是我们在"设置初始 Hash 值"小节中所说的值.
a = H 0 i ? 1 b = H 1 i ? 1 c = H 2 i ? 1 d = H 3 i ? 1 e = H 4 i ? 1 f = H 5 i ? 1 g = H 6 i ? 1 h = H 7 i ? 1 \quad a=H^{i-1}_0 \\ \quad b=H^{i-1}_1 \\ \quad c=H^{i-1}_2 \\ \quad d=H^{i-1}_3 \\ \quad e=H^{i-1}_4 \\ \quad f=H^{i-1}_5 \\ \quad g=H^{i-1}_6 \\ \quad h=H^{i-1}_7 \\ a=H0i?1?b=H1i?1?c=H2i?1?d=H3i?1?e=H4i?1?f=H5i?1?g=H6i?1?h=H7i?1?
// 3
For t=0 to 63:
{
T 1 = h + Σ 1 { 256 } ( e ) + C h ( e , f , g ) + K { 256 } t + W t T 2 = Σ 0 { 256 } ( a ) + M a j ( a , b , c ) h = g g = f f = e e = d + T 1 d = c c = b b = a a = T 1 + T 2 \qquad T_1=h+\Sigma^{\{256\}}_1(e)+Ch(e,f,g)+K^{\{256\}_t}+W_t \\ \qquad T_2=\Sigma^{\{256\}}_0(a)+Maj(a,b,c) \\ \qquad h=g \\ \qquad g=f \\ \qquad f=e \\ \qquad e=d+T_1 \\ \qquad d=c \\ \qquad c=b \\ \qquad b=a \\ \qquad a=T_1+T_2 \\ T1?=h+Σ1{256}?(e)+Ch(e,f,g)+K{256}t?+Wt?T2?=Σ0{256}?(a)+Maj(a,b,c)h=gg=ff=ee=d+T1?d=cc=bb=aa=T1?+T2?
}
//4. 计算第i t h i^{th} ith 中间 hash 值 H i H^i Hi
H 0 ( i ) = a + H 0 ( i ? 1 ) H 1 ( i ) = b + H 1 ( i ? 1 ) H 2 ( i ) = c + H 2 ( i ? 1 ) H 3 ( i ) = d + H 3 ( i ? 1 ) H 4 ( i ) = e + H 4 ( i ? 1 ) H 5 ( i ) = b + H 5 ( i ? 1 ) H 6 ( i ) = c + H 6 ( i ? 1 ) H 7 ( i ) = d + H 7 ( i ? 1 ) \quad H^{(i)}_0=a+H^{(i-1)}_0 \\ \quad H^{(i)}_1=b+H^{(i-1)}_1 \\ \quad H^{(i)}_2=c+H^{(i-1)}_2 \\ \quad H^{(i)}_3=d+H^{(i-1)}_3 \\ \quad H^{(i)}_4=e+H^{(i-1)}_4 \\ \quad H^{(i)}_5=b+H^{(i-1)}_5 \\ \quad H^{(i)}_6=c+H^{(i-1)}_6 \\ \quad H^{(i)}_7=d+H^{(i-1)}_7 \\ H0(i)?=a+H0(i?1)?H1(i)?=b+H1(i?1)?H2(i)?=c+H2(i?1)?H3(i)?=d+H3(i?1)?H4(i)?=e+H4(i?1)?H5(i)?=b+H5(i?1)?H6(i)?=c+H6(i?1)?H7(i)?=d+H7(i?1)?
}
在经过 N 次迭代之后, 最终结果为H 0 ( N ) , H 1 ( N ) , H 2 ( N ) , H 3 ( N ) , H 4 ( N ) , H 5 ( N ) , H 6 ( N ) , H 7 ( N ) H^{(N)}_0, H^{(N)}_1, H^{(N)}_2, H^{(N)}_3, H^{(N)}_4, H^{(N)}_5, H^{(N)}_6, H^{(N)}_7 H0(N)?,H1(N)?,H2(N)?,H3(N)?,H4(N)?,H5(N)?,H6(N)?,H7(N)? 的字节表示依次连接所组成的字节数组.
SHA-512#### SHA-512 算法要求输入数据的长度不能大于2 1 28 2^128 2128, 最小长度为0.
SHA-384 算法的计算过程与 SHA-512 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-384 算法的最终结果是取 SHA-512 算法结果的前 384 bit.
SHA-512/224 算法的计算过程与 SHA-512 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-512/224 算法的最终结果是取 SHA-512 算法结果的前 224 bit.
SHA-512/256 算法的计算过程与 SHA-512 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-512/256 算法的最终结果是取 SHA-512 算法结果的前 256 bit.
伪代码如下:
Σ 0 { 512 } ( x ) = R O T R 28 ( x ) ? R O T R 34 ( x ) ? R O T R 39 ( x ) \Sigma^{\{512\}}_0(x)=ROTR^{28}(x)\bigoplus ROTR^{34}(x)\bigoplus ROTR^{39}(x) Σ0{512}?(x)=ROTR28(x)?ROTR34(x)?ROTR39(x)
Σ 1 { 512 } ( x ) = R O T R 14 ( x ) ? R O T R 18 ( x ) ? R O T R 41 ( x ) \Sigma^{\{512\}}_1(x)=ROTR^{14}(x)\bigoplus ROTR^{18}(x)\bigoplus ROTR^{41}(x) Σ1{512}?(x)=ROTR14(x)?ROTR18(x)?ROTR41(x)
σ 0 { 512 } ( x ) = R O T R 1 ( x ) ? R O T R 8 ( x ) ? S H R 7 ( x ) \sigma^{\{512\}}_0(x)=ROTR^1(x)\bigoplus ROTR^8(x)\bigoplus SHR^7(x) σ0{512}?(x)=ROTR1(x)?ROTR8(x)?SHR7(x)
σ 1 { 512 } ( x ) = R O T R 19 ( x ) ? R O T R 61 ( x ) ? S H R 6 ( x ) \sigma^{\{512\}}_1(x)=ROTR^{19}(x)\bigoplus ROTR^{61}(x)\bigoplus SHR^6(x) σ1{512}?(x)=ROTR19(x)?ROTR61(x)?SHR6(x)
For i=1 to N:
{
//1. 计算W t W_t Wt?
W t \quad W_t Wt? ={ M t ( 0 ) , 0 ≤ t ≤ 15 σ 1 { 512 } ( W t ? 2 ) + W t ? 7 + σ 0 { 512 } ( W t ? 15 ) + W t ? 16 , 16 ≤ t ≤ 79 \begin{cases} M^{(0)}_t, \qquad 0\leq t\leq15\\ \quad \\ \sigma^{\{512\}}_1(W_{t-2})+W_{t-7}+\sigma^{\{512\}}_0(W_{t-15})+W_{t-16}, \qquad 16\leq t\leq79\\ \end{cases} ??????Mt(0)?,0≤t≤15σ1{512}?(Wt?2?)+Wt?7?+σ0{512}?(Wt?15?)+Wt?16?,16≤t≤79?
//2. 初始化工作变量 a, b, c, d, e, f, g, h. 他们用来存储在第 i-1 次迭代式的 Hash 值
// 他们的初始值就是我们在"设置初始 Hash 值"小节中所说的值.
a = H 0 i ? 1 b = H 1 i ? 1 c = H 2 i ? 1 d = H 3 i ? 1 e = H 4 i ? 1 f = H 5 i ? 1 g = H 6 i ? 1 h = H 7 i ? 1 \quad a=H^{i-1}_0 \\ \quad b=H^{i-1}_1 \\ \quad c=H^{i-1}_2 \\ \quad d=H^{i-1}_3 \\ \quad e=H^{i-1}_4 \\ \quad f=H^{i-1}_5 \\ \quad g=H^{i-1}_6 \\ \quad h=H^{i-1}_7 \\ a=H0i?1?b=H1i?1?c=H2i?1?d=H3i?1?e=H4i?1?f=H5i?1?g=H6i?1?h=H7i?1?
// 3
For t=0 to 79:
{
T 1 = h + Σ 1 { 512 } ( e ) + C h ( e , f , g ) + K { 512 } t + W t T 2 = Σ 0 { 512 } ( a ) + M a j ( a , b , c ) h = g g = f f = e e = d + T 1 d = c c = b b = a a = T 1 + T 2 \qquad T_1=h+\Sigma^{\{512\}}_1(e)+Ch(e,f,g)+K^{\{512\}_t}+W_t \\ \qquad T_2=\Sigma^{\{512\}}_0(a)+Maj(a,b,c) \\ \qquad h=g \\ \qquad g=f \\ \qquad f=e \\ \qquad e=d+T_1 \\ \qquad d=c \\ \qquad c=b \\ \qquad b=a \\ \qquad a=T_1+T_2 \\ T1?=h+Σ1{512}?(e)+Ch(e,f,g)+K{512}t?+Wt?T2?=Σ0{512}?(a)+Maj(a,b,c)h=gg=ff=ee=d+T1?d=cc=bb=aa=T1?+T2?
}
//4. 计算第i t h i^{th} ith 中间 hash 值 H i H^i Hi
H 0 ( i ) = a + H 0 ( i ? 1 ) H 1 ( i ) = b + H 1 ( i ? 1 ) H 2 ( i ) = c + H 2 ( i ? 1 ) H 3 ( i ) = d + H 3 ( i ? 1 ) H 4 ( i ) = e + H 4 ( i ? 1 ) H 5 ( i ) = b + H 5 ( i ? 1 ) H 6 ( i ) = c + H 6 ( i ? 1 ) H 7 ( i ) = d + H 7 ( i ? 1 ) \quad H^{(i)}_0=a+H^{(i-1)}_0 \\ \quad H^{(i)}_1=b+H^{(i-1)}_1 \\ \quad H^{(i)}_2=c+H^{(i-1)}_2 \\ \quad H^{(i)}_3=d+H^{(i-1)}_3 \\ \quad H^{(i)}_4=e+H^{(i-1)}_4 \\ \quad H^{(i)}_5=b+H^{(i-1)}_5 \\ \quad H^{(i)}_6=c+H^{(i-1)}_6 \\ \quad H^{(i)}_7=d+H^{(i-1)}_7 \\ H0(i)?=a+H0(i?1)?H1(i)?=b+H1(i?1)?H2(i)?=c+H2(i?1)?H3(i)?=d+H3(i?1)?H4(i)?=e+H4(i?1)?H5(i)?=b+H5(i?1)?H6(i)?=c+H6(i?1)?H7(i)?=d+H7(i?1)?
}
在经过 N 次迭代之后, 最终结果为H 0 ( N ) , H 1 ( N ) , H 2 ( N ) , H 3 ( N ) , H 4 ( N ) , H 5 ( N ) , H 6 ( N ) , H 7 ( N ) H^{(N)}_0, H^{(N)}_1, H^{(N)}_2, H^{(N)}_3, H^{(N)}_4, H^{(N)}_5, H^{(N)}_6, H^{(N)}_7 H0(N)?,H1(N)?,H2(N)?,H3(N)?,H4(N)?,H5(N)?,H6(N)?,H7(N)? 的字节表示依次连接所组成的字节数组.
算法实现## 本人使用 go 语言实现了该算法. github:https://github.com/UselezzProgrammer/mycrypto
END!

    推荐阅读