数据加密方法总结---散列函数加密(彩虹表、MD、SHA、HMAC)

1单向加密

特点:

  1. 雪崩效应、定长输出、不可逆;
  2. 可以确保数据的完整性;
  3. 主要算法:MD5(message digest algorithm)及其家族、SHA(secure hash algorithm)家族等

单向散列算法就是哈希算法——将任意长度的信息压缩到某一固定长度(信息摘要)的函数(该过程不可逆)。

彩虹表

彩虹表不是“密码-明文”的存储。

c = h a s h ( m ) c=hash(m) c=hash(m)逆向得到原始明文有三种方法:

  1. 暴力破解
  2. 字典法:提前构建一个“明文–密文”对应的大数据库,破解时直接进行查找,但是这样的数据库维护起来十分麻烦且安全性难以维护;
  3. 构建彩虹表:在字典法的基础上改进,以时间换空间。

因为存储所有的明文-密文对需要太多的空间,所以使用一种方法来减少存储空间的需求——预计算的哈希链集。

图片说明

其中H函数是需要破解的哈希函数。R函数是构建这条链时定义的一个函数:它的值域和定义域与H函数相反,通过R函数可以将哈希值归约为一个与原文相同格式的值对R函数唯一的要求就是可以把任意哈希值映射成特定字符的纯文本值。

这样的彩虹表只需要存储开头和结尾的节点。

彩虹表的使用方法

  1. 首先把给定的密文使用R函数归约为一个特定的字符,如4D5E6F使用R函数归约为ccc,发现恰好符合上述的哈希链,则证明4D5E6F对应的明文可能存在开头为aaa结尾为ccc的哈希链中,但是这个不一定是,因为可能H函数和R函数可能发生碰撞,不同的输入可能得到相同的输出;
  2. 然后从aaa开始重复哈希链的生成过程,如果存在符合的条件,则破解成功;如果找不到满足条件的哈希链,则再次对已经经过一次R函数处理过的值再次使用R函数处理,如果处理k(k为哈希链中重复H函数和R函数的次数)次均没有找到,则证明该密文的明文不存在该哈希链中。

彩虹表的防御措施

  1. 主要是对H函数进行处理:加盐,因为一旦每个用户的“加盐量”不同,那么每个函数的H函数都不一样,产生的彩虹表也就不同;
  2. 提高H函数的计算难度,这样的话意味着彩虹表的生成时间会大大增加,但是同时破解的难度也会对应的增加;

彩虹表存在的一些问题

  1. 对R函数要求特别高:要减少碰撞率,因为一旦碰撞率高的话,哈希链能解密的明文数量远远达不到理论的数量,所以可能会造成大量的容易和重复,所以R函数需要尽量保证输出值在值域内均匀分布,以尽量减少碰撞;

MD5及其类似算法

MD4(message digest 信息摘要)-3轮 × 16步–输出128位

算法步骤

  1. 数据填充:首先将数据的位数填充到512的倍数(和MD5的一样);

  2. 分组处理:将数据划分为512位每组,再对每一组分别进行处理;

  3. 将每组512位的数据划分为16个子分块,处理数据段的三个函数:

    1. F ( X , Y , Z ) = ( X & Y ) ∣ ( ( ∼ X ) & Z ) F(X,Y,Z)=(X \& Y)|((\sim X) \& Z) F(X,Y,Z)=(X&Y)((X)&Z)
    2. G ( X , Y , Z ) = ( X & Z ) ∣ ( X & Z ) ∣ ( Y & Z ) G(X,Y,Z)=(X \& Z)|(X \& Z)|(Y \& Z) G(X,Y,Z)=(X&Z)(X&Z)(Y&Z)
    3. H ( X , Y , Z ) = X ∧ Y ∧ Z H(X,Y,Z)=X^{\land} Y ^{\land} Z H(X,Y,Z)=XYZ

    然后对处理好的数据以512位为一个单位进行处理,每个单位的数据都要进行3轮的逻辑处理,在3轮中分别使用不同的函数 F 、 G 、 H F、G、H FGH,每一轮以ABCD和当前的单位数据为输入,处理后存储到四个32位的寄存器 A 、 B 、 C 、 D A、B、C、D ABCD中,如此进行循环;

  4. 输出:进行步骤3的循环,如果当前的已经是最后一个单位的数据,则将四个寄存器内的变量进行顺序拼接,即为MD5的输出结果。

MD5(message digest 信息摘要)-4轮 × 16步–输出128位

简单来说,MD5就是把数据以512位进行分组,来处理输入的信息,每一组后面再划分成16个32位子分组,经过一系列处理后,输出一个由4个32位分组组成的数据,这4个32位分组级联,形成一个128位散列值。

算法步骤:

  1. 按位补充数据:将数据进行填充,要求数据的最终位数对512取模运算,结果为448,即数据补位后,其位数距离512的整数倍只差64。需要注意的是,补位位数为1~512,也就意味着即便现有的数据位数满足上面的条件,也要进行补位。==补位的实现过程:==首先在数据后面补一个1,然后一直补0,直至满足要求;

  2. 扩展长度:完成补位后,将一个表示数据原始长度的64位的数据放在最后(如果原数据的长度大于 2 64 2^{64} 264,则只存储低64位的值,即数据长度 % 2 64 2^{64} 264),此时,数据的长度正好为512的倍数;

  3. 初始化MD缓存器:因为MD5最终输出的是一个128位的散列值,所以需要四个32位的寄存器 A , B , C , D A,B,C,D A,B,C,D,将其分别初始化为:

    1. A:0x 67 45 23 01
    2. B:0x ef cd ab 89
    3. C:0x 98 ba dc fe
    4. D:0x 10 32 54 76

    这样初始化的原因是——进行小端表示后,四个缓存变量连起来就是(小端表示法:将最低位放在最高位,依次进行调换,如0x 12 34 56 78,小端表示为0x 78 56 34 12):

    0x 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10

  4. 处理数据段:首先定义四个函数:( & 、 ∼ 、 ∣ 、 ⊕ \&、\sim、|、\oplus &)分别表示AND、NOT、OR、XOR

    1. F ( X , Y , Z ) = ( X & Y ) ∣ ( ( ∼ X ) & Z ) F(X,Y,Z)=(X \& Y)|((\sim X) \& Z) F(X,Y,Z)=(X&Y)((X)&Z)
    2. G ( X , Y , Z ) = ( X & Z ) ∣ ( ( ∼ Z ) & Y ) G(X,Y,Z)=(X \& Z)|((\sim Z) \& Y) G(X,Y,Z)=(X&Z)((Z)&Y)
    3. H ( X , Y , Z ) = X ⊕ Y ⊕ Z H(X,Y,Z)=X{\oplus} Y {\oplus} Z H(X,Y,Z)=XYZ
    4. I ( X , Y , Z ) = Y ⊕ ( X ∣ ( ∼ Z ) ) I(X,Y,Z)=Y{\oplus}(X|(\sim Z)) I(X,Y,Z)=Y(X(Z))

    然后对处理好的数据以512位为一个单位进行处理,每个单位的数据都要进行四轮的逻辑处理,在四轮中分别使用不同的函数 F 、 G 、 H 、 I F、G、H、I FGHI,每一轮以ABCD和当前的单位数据为输入,处理后存储到四个32位的寄存器 A 、 B 、 C 、 D A、B、C、D ABCD中,如此进行循环;

  5. 输出:进行步骤4的循环,如果当前的已经是最后一个单位的数据,则将四个寄存器内的变量进行顺序拼接,即为MD5的输出结果。

==特性:==主要特点是不可逆,相同数据的MD5一定是相同的,而一般情况下,不同数据的MD5是一定不同的(存在极少的特殊情况)

  1. ==压缩性:==任意长度的数据,经过处理后的MD5都是一样长度的——128位;
  2. ==易于计算:==根据原始输入数据计算MD5非常简单且容易;
  3. ==抗修改性:==因为MD5具有雪崩效应,所以对原始数据进行十分微小的修改,MD5也会产生非常不同的值,且差别非常大;
  4. ==弱抗碰撞:==已知原数据及其MD5,想要找到一个具有相同MD5的数据是非常困难的(伪造数据非常困难);
  5. ==强抗碰撞:==想找到两个MD5相同的数据是非常困难的。

MD5的防御手段

  1. 加盐:在已有的明文上添加系统随机产生的盐值,每次密文对比之前也是先对输入的明文进行加盐,然后进行比对;

数据处理的过程就是每次把512位的数据压缩为128位的Hash值,压缩函数每一轮均使用16次对应的非线性布尔函数,每次均更新 A 、 B 、 C 、 D A、B、C、D ABCD的值,压缩函数为(其中 < < < s <<<s <<<s表示左移S位, M j M_j Mj表示第j个分组,其中 j ∈ [ 0 , 15 ] j\in [0,15] j[0,15] t i t_i ti表示 2 32 × a b s ( s i n ( i ) ) 2^{32} \times abs(sin(i)) 232×abs(sin(i))的整数部分,其中 i ∈ [ 1 , 64 ] i\in[1,64] i[1,64]):

  1. F F ( a , b , c , d , M j , s , t i ) = b + ( ( a + F ( b , c , d ) + M j + t i ) < < < s ) FF(a, b, c, d, M_j, s, t_i) = b + ((a + F(b, c, d) + M_j+ t_i) <<< s) FF(a,b,c,d,Mj,s,ti)=b+((a+F(b,c,d)+Mj+ti)<<<s)

  2. G G ( a , b , c , d , M j , s , t i ) = b + ( ( a + G ( b , c , d ) + M j + t i ) < < < s ) GG(a, b, c, d, M_j, s, t_i) =b + ((a + G(b, c, d) + M_j+ t_i) <<< s) GG(a,b,c,d,Mj,s,ti)=b+((a+G(b,c,d)+Mj+ti)<<<s)

  3. H H ( a , b , c , d , M j , s , t i ) = b + ( ( a + H ( b , c , d ) + M j + t i ) < < < s ) HH(a, b, c, d, M_j, s, t_i) =b + ((a + H(b, c, d) + M_j+ t_i) <<< s) HH(a,b,c,d,Mj,s,ti)=b+((a+H(b,c,d)+Mj+ti)<<<s)

  4. I I ( a , b , c , d , M j , s , t i ) = b + ( ( a + I ( b , c , d ) + M j + t i ) < < < s ) II(a, b, c, d, M_j, s, t_i) =b + ((a + I(b, c, d) + M_j+ t_i) <<< s) II(a,b,c,d,Mj,s,ti)=b+((a+I(b,c,d)+Mj+ti)<<<s)

  5. 这四轮(64步)是:
    第一轮
    FF(a,b,c,d,M0,7,0xd76aa478)
    FF(d,a,b,c,M1,12,0xe8c7b756)
    FF(c,d,a,b,M2,17,0x242070db)
    FF(b,c,d,a,M3,22,0xc1bdceee)
    FF(a,b,c,d,M4,7,0xf57c0faf)
    FF(d,a,b,c,M5,12,0x4787c62a)
    FF(c,d,a,b,M6,17,0xa8304613)
    FF(b,c,d,a,M7,22,0xfd469501)
    FF(a,b,c,d,M8,7,0x698098d8)
    FF(d,a,b,c,M9,12,0x8b44f7af)
    FF(c,d,a,b,M10,17,0xffff5bb1)
    FF(b,c,d,a,M11,22,0x895cd7be)
    FF(a,b,c,d,M12,7,0x6b901122)
    FF(d,a,b,c,M13,12,0xfd987193)
    FF(c,d,a,b,M14,17,0xa679438e)
    FF(b,c,d,a,M15,22,0x49b40821)
    第二轮
    GG(a,b,c,d,M1,5,0xf61e2562)
    GG(d,a,b,c,M6,9,0xc040b340)
    GG(c,d,a,b,M11,14,0x265e5a51)
    GG(b,c,d,a,M0,20,0xe9b6c7aa)
    GG(a,b,c,d,M5,5,0xd62f105d)
    GG(d,a,b,c,M10,9,0x02441453)
    GG(c,d,a,b,M15,14,0xd8a1e681)
    GG(b,c,d,a,M4,20,0xe7d3fbc8)
    GG(a,b,c,d,M9,5,0x21e1cde6)
    GG(d,a,b,c,M14,9,0xc33707d6)
    GG(c,d,a,b,M3,14,0xf4d50d87)
    GG(b,c,d,a,M8,20,0x455a14ed)
    GG(a,b,c,d,M13,5,0xa9e3e905)
    GG(d,a,b,c,M2,9,0xfcefa3f8)
    GG(c,d,a,b,M7,14,0x676f02d9)
    GG(b,c,d,a,M12,20,0x8d2a4c8a)
    第三轮
    HH(a,b,c,d,M5,4,0xfffa3942)
    HH(d,a,b,c,M8,11,0x8771f681)
    HH(c,d,a,b,M11,16,0x6d9d6122)
    HH(b,c,d,a,M14,23,0xfde5380c)
    HH(a,b,c,d,M1,4,0xa4beea44)
    HH(d,a,b,c,M4,11,0x4bdecfa9)
    HH(c,d,a,b,M7,16,0xf6bb4b60)
    HH(b,c,d,a,M10,23,0xbebfbc70)
    HH(a,b,c,d,M13,4,0x289b7ec6)
    HH(d,a,b,c,M0,11,0xeaa127fa)
    HH(c,d,a,b,M3,16,0xd4ef3085)
    HH(b,c,d,a,M6,23,0x04881d05)
    HH(a,b,c,d,M9,4,0xd9d4d039)
    HH(d,a,b,c,M12,11,0xe6db99e5)
    HH(c,d,a,b,M15,16,0x1fa27cf8)
    HH(b,c,d,a,M2,23,0xc4ac5665)
    第四轮
    II(a,b,c,d,M0,6,0xf4292244)
    II(d,a,b,c,M7,10,0x432aff97)
    II(c,d,a,b,M14,15,0xab9423a7)
    II(b,c,d,a,M5,21,0xfc93a039)
    II(a,b,c,d,M12,6,0x655b59c3)
    II(d,a,b,c,M3,10,0x8f0ccc92)
    II(c,d,a,b,M10,15,0xffeff47d)
    II(b,c,d,a,M1,21,0x85845dd1)
    II(a,b,c,d,M8,6,0x6fa87e4f)
    II(d,a,b,c,M15,10,0xfe2ce6e0)
    II(c,d,a,b,M6,15,0xa3014314)
    II(b,c,d,a,M13,21,0x4e0811a1)
    II(a,b,c,d,M4,6,0xf7537e82)
    II(d,a,b,c,M11,10,0xbd3af235)
    II(c,d,a,b,M2,15,0x2ad7d2bb)
    II(b,c,d,a,M9,21,0xeb86d391)

SHA算法家族(secure hash algorithm 安全哈希算法)(补充一下)

有很多种类:SHA-1、SHA-256、SHA-384、SHA-512等,分别可以产生160位、256位、384位、512位的散列值。

SHA-1

于MD5相比,存在以下区别

MD5SHA-1SHA-256
输入长度任意不能超过 2 64 2^{64} 264任意
输出长度128160256
每个数据块的处理步骤4轮 × 16次 = 64次4轮 × 20次 = 80次64次
基本逻辑函数4个4个6个
常数数量64个 t i t_i ti的取值+4个寄存器初始值4个 K t K_t Kt的取值+5个寄存器的初始值8个寄存器的初始值+64个 K j K_j Kj的取值
寄存器存储小端存储大端存储大端存储

算法步骤:

  1. 按位补充(与MD5一样,长度补充到512的整数倍-64,补位的数量范围在1-512);

  2. 扩展长度(与MD5一样,尾部加上64位表示原始长度的信息);

  3. 初始化MD缓存器:与MD5不同的是,这里使用了5个32位寄存器,且寄存器使用大端存储的方式,前四个包含的值大小与MD5的相同,具体为:

    1. H 1 H_1 H1:0x 67 45 23 01
    2. H 2 H_2 H2:0x ef cd ab 89
    3. H 3 H_3 H3:0x 98 ba dc fe
    4. H 4 H_4 H4:0x 10 32 54 76
    5. H 5 H_5 H5:0x c3 d2 e1 f0
  4. 处理数据段:首先定义四个函数:( & 、 ∼ 、 ∣ 、 ⊕ \&、\sim、|、\oplus &)分别表示AND、NOT、OR、XOR

    1. F ( X , Y , Z ) = ( X & Y ) ∣ ( ( ∼ X ) & Z ) , t ∈ [ 0 , 19 ] F(X,Y,Z)=(X \& Y)|((\sim X) \& Z), t \in [0,19] F(X,Y,Z)=(X&Y)((X)&Z),t[0,19]
    2. G ( X , Y , Z ) = X ⊕ Y ⊕ Z , t ∈ [ 20 , 39 ] G(X,Y,Z)=X{\oplus} Y {\oplus} Z, t \in [20,39] G(X,Y,Z)=XYZ,t[20,39]
    3. H ( X , Y , Z ) = ( X & Y ) ∣ ( Y & Z ) ∣ ( X & Z ) , t ∈ [ 40 , 59 ] H(X,Y,Z)=(X \& Y)|(Y \& Z)|(X \& Z), t \in [40,59] H(X,Y,Z)=(X&Y)(Y&Z)(X&Z),t[40,59]
    4. I ( X , Y , Z ) = X ⊕ Y ⊕ Z , t ∈ [ 60 , 79 ] I(X,Y,Z)=X{\oplus} Y {\oplus} Z, t \in [60,79] I(X,Y,Z)=XYZ,t[60,79]

    与MD5不同的是,这四个函数的使用方法不同,具体的使用范围详见上面的t的范围,其中 t t t是步骤的索引值。

    每个数据段的长度为512位,处理方法和MD5一样,但是会将每个512位的数据先划分成16份子明文分组 M t , t ∈ [ 0 , 15 ] M_t, t \in [0,15] Mt,t[0,15],每组32位,然后将16份子明文分组扩充为80份子明文分组 W [ t ] , t ∈ [ 0 , 79 ] W[t],t \in [0,79] W[t],t[0,79],扩充方法为:

    W t = M t , t ∈ [ 0 , 15 ] W t = ( W t − 3 ⊕ W t − 8 ⊕ W t − 14 ⊕ W t − 16 ) , t ∈ [ 16 , 79 ] W_t = M_t, t \in [0,15] \\ W_t = (W_{t-3} {\oplus} W_{t-8} {\oplus} W_{t-14} {\oplus} W_{t-16}), t\in [16,79] Wt=Mt,t[0,15]Wt=(Wt3Wt8Wt14Wt16),t[16,79]

    对数据段的处理共四轮,每轮20步,共计80步。

    80轮的共用一个操作步骤:

    A = ( A < < < 5 ) + f ( B , C , D ) + E + W t + K t , B = A , C = ( B < < < 30 ) , D = C , E = D A=(A<<<5) + f(B,C,D)+E+W_t+K_t,\\B=A,\\C=(B<<<30),\\D=C,\\E=D A=(A<<<5)+f(B,C,D)+E+Wt+Kt,B=A,C=(B<<<30),D=C,E=D

    其中 f ( ) f() f()函数根据处理步骤的索引进行动态变化, K t K_t Kt是固定常数, W t W_t Wt是子明文分组 W [ t ] W[t] W[t]

    其中 K t K_t Kt的取值:

    1. K t = 5 a 827999 , t ∈ [ 0 , 19 ] K_t= 5a827999, t \in [0,19] Kt=5a827999,t[0,19]
    2. K t = 6 e d 9 e b a 1 , t ∈ [ 20 , 39 ] K_t=6ed9eba1, t \in [20,39] Kt=6ed9eba1,t[20,39]
    3. K t = 8 f 188 c d c , t ∈ [ 40 , 59 ] K_t=8f188cdc, t \in [40,59] Kt=8f188cdc,t[40,59]
    4. K t = c a 62 c 1 d 6 , t ∈ [ 60 , 79 ] K_t=ca62c1d6, t \in [60,79] Kt=ca62c1d6,t[60,79]
  5. 输出:最后将5个32位寄存器的数据取出,分别和A,B,C,D,E中的数据进行相加—— H 1 = H 1 + A , H 2 = H 2 + B , H 3 = H 3 + C , H 4 = H 4 + D , H 5 = H 5 + E H_1 = H_1 + A,H_2 = H_2 + B,H_3 = H_3 + C,H_4 = H_4 + D,H_5 = H_5 + E H1=H1+A,H2=H2+B,H3=H3+C,H4=H4+D,H5=H5+E,然后进行拼接即为最终的160位的输出。

SHA-256

算法步骤:

  1. 按位补充(与MD5、SHA-1一样,长度补充到512的整数倍-64,补位的数量范围在1-512);

  2. 扩展长度(与MD5、SHA-1一样,尾部加上64位表示原始长度的信息);

  3. 初始化MD缓存器:与MD5、SHA-1不同的是,这里使用了8个32位寄存器,且寄存器使用大端存储的方式,取值为前8个素数{2,3,5,7,11,13,17,19}的平方根的小数部分的前32位,如2的平方根为1.41421356…,就取小数部分的前32位:41421356…,然后转换为16进制数:0x6a09e667

    1. H 1 = 0 x 6 a 09 e 667 H_1=0x6a09e667 H1=0x6a09e667;
    2. H 2 = 0 x b b 67 a e 85 H_2=0xbb67ae85 H2=0xbb67ae85;
    3. H 3 = 0 x 3 c 6 e f 372 H_3=0x3c6ef372 H3=0x3c6ef372;
    4. H 4 = 0 x a 54 f f 53 a H_4=0xa54ff53a H4=0xa54ff53a;
    5. H 5 = 0 x 510 e 527 f H_5=0x510e527f H5=0x510e527f;
    6. H 6 = 0 x 9 b 05688 c H_6=0x9b05688c H6=0x9b05688c;
    7. H 7 = 0 x 1 f 83 d 9 a b H_7=0x1f83d9ab H7=0x1f83d9ab;
    8. H 8 = 0 x 5 b e 0 c d 19 H_8=0x5be0cd19 H8=0x5be0cd19;
  4. 处理数据段:先定义6个函数:( & 、 ∼ 、 ∣ 、 ⊕ 、 S n 、 R n \&、\sim、|、\oplus、S^n、R^n &SnRn)分别表示AND、NOT、OR、XOR、循环右移n位、右移n位

    1. C h ( X , Y , Z ) = ( X & Y ) ⊕ ( ( ∼ X ) & Z ) Ch(X,Y,Z)=(X \& Y)\oplus((\sim X) \& Z) Ch(X,Y,Z)=(X&Y)((X)&Z)
    2. M a ( X , Y , Z ) = ( X & Y ) ⊕ ( Y & Z ) ⊕ ( X & Z ) Ma(X,Y,Z)=(X \& Y)\oplus(Y \& Z)\oplus(X \& Z) Ma(X,Y,Z)=(X&Y)(Y&Z)(X&Z)
    3. ∑ 0 ( x ) = S 2 ( x ) ⊕ S 13 ( x ) ⊕ S 22 \sum_0(x) = S^{2}(x) \oplus S^{13}(x) \oplus S^{22} 0(x)=S2(x)S13(x)S22
    4. ∑ 1 ( x ) = S 6 ( x ) ⊕ S 11 ( x ) ⊕ S 25 \sum_1(x) = S^{6}(x) \oplus S^{11}(x) \oplus S^{25} 1(x)=S6(x)S11(x)S25
    5. σ 0 ( x ) = S 7 ( x ) ⊕ S 18 ( x ) ⊕ R 3 \sigma_0(x) = S^{7}(x) \oplus S^{18}(x) \oplus R^{3} σ0(x)=S7(x)S18(x)R3
    6. σ 1 ( x ) = S 17 ( x ) ⊕ S 19 ( x ) ⊕ R 10 \sigma_1(x) = S^{17}(x) \oplus S^{19}(x) \oplus R^{10} σ1(x)=S17(x)S19(x)R10

    每个数据段的长度为512位,处理方法和MD5一样,但是会将每个512位的数据先划分成16份子明文分组 M t , t ∈ [ 0 , 15 ] M_t, t \in [0,15] Mt,t[0,15],每组32位,然后将16份子明文分组扩充为64份子明文分组 W [ t ] , t ∈ [ 0 , 79 ] W[t],t \in [0,79] W[t],t[0,79],扩充方法为:

    W t = M t , t ∈ [ 0 , 15 ] W t = ( W t − 3 ⊕ W t − 8 ⊕ W t − 14 ⊕ W t − 16 ) , t ∈ [ 16 , 63 ] W_t = M_t, t \in [0,15] \\ W_t = (W_{t-3} {\oplus} W_{t-8} {\oplus} W_{t-14} {\oplus} W_{t-16}), t\in [16,63] Wt=Mt,t[0,15]Wt=(Wt3Wt8Wt14Wt16),t[16,63]

    假设完成扩展长度后数据长度为L,需要处理的数据块数量为 L / 512 = N L/512 = N L/512=N,处理步骤伪代码为:

    其中 H i 0 H^{0}_i Hi0分别对应初始的8个寄存器初始值 H i H_i Hi K j K_j Kj分别对应前64个素数{2,3,5,7,11,13…}立方根的小数部分的前32位 W j W_j Wj子明文分组

    f o r ( i = 1 → N ) − − − l o o p 1 a = H 1 ( i − 1 ) b = H 2 ( i − 1 ) c = H 3 ( i − 1 ) d = H 4 ( i − 1 ) e = H 5 ( i − 1 ) f = H 6 ( i − 1 ) g = H 7 ( i − 1 ) h = H 8 ( i − 1 ) f o r ( j = 0 → 63 ) − − − l o o p 2 T 1 = h + ∑ 1 ( e ) + C h ( e , f , g ) + K j + W j T 2 = ∑ 0 ( 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 e n d − − l o o p 2 H 1 ( i ) = a + H 1 ( i − 1 ) H 2 ( i ) = b + H 2 ( i − 1 ) H 3 ( i ) = c + H 3 ( i − 1 ) H 4 ( i ) = d + H 4 ( i − 1 ) H 5 ( i ) = e + H 5 ( i − 1 ) H 6 ( i ) = f + H 6 ( i − 1 ) H 7 ( i ) = g + H 7 ( i − 1 ) H 8 ( i ) = h + H 8 ( i − 1 ) e n d − − l o o p 1 \begin{aligned} for (i=1& \rightarrow N)---loop1 \\ & a = H^{(i-1)}_1 \\&b = H^{(i-1)}_2 \\&c = H^{(i-1)}_3 \\&d = H^{(i-1)}_4 \\&e = H^{(i-1)}_5 \\&f = H^{(i-1)}_6 \\&g = H^{(i-1)}_7 \\&h = H^{(i-1)}_8 \\\\ for& (j=0 \rightarrow 63)---loop2\\ &T_1=h+\sum_1(e) + Ch(e,f,g)+K_j+W_j\\& T_2=\sum_0(a)+Ma_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 \\ end&--loop2\\ \\H^{(i)}_1 &= a+H^{(i-1)}_1 \\ H^{(i)}_2 &= b+H^{(i-1)}_2 \\ H^{(i)}_3 &= c+H^{(i-1)}_3 \\ H^{(i)}_4 &= d+H^{(i-1)}_4 \\ H^{(i)}_5 &= e+H^{(i-1)}_5 \\ H^{(i)}_6 &= f+H^{(i-1)}_6 \\ H^{(i)}_7 &= g+H^{(i-1)}_7 \\ H^{(i)}_8 &= h+H^{(i-1)}_8 \\end--loop1 \end{aligned} for(i=1forendH1(i)H2(i)H3(i)H4(i)H5(i)H6(i)H7(i)H8(i)endloop1N)loop1a=H1(i1)b=H2(i1)c=H3(i1)d=H4(i1)e=H5(i1)f=H6(i1)g=H7(i1)h=H8(i1)(j=063)loop2T1=h+1(e)+Ch(e,f,g)+Kj+WjT2=0(a)+Maj(a,b,c)h=gg=ff=ee=d+T1d=cc=bb=aa=T1+T2loop2=a+H1(i1)=b+H2(i1)=c+H3(i1)=d+H4(i1)=e+H5(i1)=f+H6(i1)=g+H7(i1)=h+H8(i1)

  5. 输出:最后将 H 1 N − H 8 N H^{N}_{1}-H^{N}_{8} H1NH8N拼接起来,形成256位的输出结果。

HMAC(hash message authentication code哈希信息鉴别码)

后续更新
------------2021.6.7日更新------------
首先是MAC(message authentication code信息鉴别码),MAC的实现由MAC算法+密钥+需要加密的明文信息三部分组成,其中发送方和接收方的密钥是一致的

与Hash算法相比,Hash方法只能保证信息的完整性——信息摘要A是信息B生成的,而MAC可以确保信息的正确性和信息完整性——发送的是信息A而不是信息C。

对于HMAC而言,意味着MAC算法采用Hash函数,所以HMAC的加密强度取决于采用的Hash函数的加密强度、Hash函数的输出长度、Hash函数密钥的长度和质量。

HMAC会进行两次Hash函数计算,而提供的密钥会用来产生内部密钥和外部密钥。

  1. 第一次进行Hash计算时,通过信息和内部密钥产生一个内部Hash;
  2. 第二次进行Hash计算时,通过内部Hash和外部密钥产生HMAC的最终结果。

公式

在这里插入图片描述

其中

  1. H表示Hash函数;
  2. K是密钥;
  3. ipad是内部密钥;
  4. opad是外部密钥;
  5. m是需要信息鉴别的信息;
  6. 需要注意的是,如果K的长度大于Hash函数分块的数量,则先使用Hash函数对密钥K进行处理,然后再使用;

在这里插入图片描述

算法步骤(因为HMAC中间使用的是Hash函数,关于Hash函数的加密过程前文中已经包含,所以不再进行详细描述)(根据上面的叙述,HMAC除了Hash函数部分所需要的常数外,还需要提供以下几个常数:初始密钥K、内部密钥innerKey、外部密钥outerKey):

  1. 对初始密钥K进行处理:假设采用的Hash函数的分组每组大小为b位,如果K的长度大于b,则使用Hash函数进行处理 K ′ = H a s h ( K ) K'=Hash(K) K=Hash(K);若原始的K或使用Hash函数处理过的K的长度小于b,则在右侧填充0,直至长度等于b;最终 K ′ K' K的长度一定是等于b的
  2. 分别得到内部密钥和外部密钥 i p a d = K ′ ⊕ i n n e r K e y , o p a d = K ′ ⊕ o u t e r K e y ipad = K' \oplus innerKey,opad=K' \oplus outerKey ipad=KinnerKeyopad=KouterKey,其中inner是 b / 8 b/8 b/8 00110110 ( 十 六 进 制 36 ) 00110110(十六进制36) 0011011036的重复相连(0011011000110110…共b/8个…00110110),outer是个 01011100 ( 十 六 进 制 5 c ) 01011100(十六进制5c) 010111005c的重复相连;
  3. 第一次Hash计算:在ipad后面拼接信息M,然后经过Hash函数得到内部Hash——h,此时的结果对于上面公式的 H ( ( K ′ ⊕ i p a d ) ∣ ∣ M ) H((K' \oplus ipad) || M) H((Kipad)M),然后根据h的长度,进行填充,直至其长度为b,得到 h ′ h' h
  4. 第二次Hash计算:在opad后面拼接第3步得到的 h ′ h' h,然后经过Hash函数得到HMAC的输出结果。

需要注意的是,HMAC是信息鉴别码,所以它并不加密信息,而是把经过Hash处理过的信息作为认证码,并且信息必须要和HMAC得到的Hash值一起传输,进行鉴别时,拥有密钥的人对信息再次进行Hash,如果信息没有发生任何改变,得到的Hash值与接收到的Hash值将会是一致的。

简单来说就是,对于同一个密钥K,只有发送方A和接收方B持有该密钥,发送方根据密钥K对随机信息M(M的内容并不重要)采用HMAC算法进行处理,得到信息鉴别码 H 1 H_1 H1,将信息M和信息鉴别码 H 1 H_1 H1都传输给B,然后B根据密钥K对随机信息M采用同样的HMAC算法进行处理,若得到的信息鉴别码 H 2 H_2 H2 H 1 H_1 H1完全一致,则证明发送方是A,注意,HMAC的作用是证明发送信息的人是A,而不是信息M的加密结果,一旦验证完身份,信息M就没用了。

因此Hash拥有了以下安全性

  1. 因为只有通信双方持有密钥,所以一旦信息在通信过程中被截取,第三方只能拥有随机信息M和用来验证的信息鉴别码 H 1 H_1 H1,因为不知道密钥,所以无法再次通过某一HMAC算法得到同样的信息鉴别码,而仅根据M和 H 1 H_1 H1也无法破解出密钥;
  2. HMAC是时效性的,一旦使用完就失效,对应的密钥也失效。而对于加密算法而言,一旦算法被破解,之前的加密结果可能会被破解。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
HMAC-SHA1是一种常用的加密算法,可以使用Java中的javax.crypto库来实现。以下是Java实现HMAC-SHA1加密的示例代码: ```java import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; public class HmacSha1 { public static void main(String[] args) { String text = "hello world"; String key = "secret_key"; String hmacSha1 = hmacSha1(text, key); System.out.println(hmacSha1); } public static String hmacSha1(String text, String key) { try { Mac hmac = Mac.getInstance("HmacSHA1"); SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); hmac.init(secretKey); byte[] digest = hmac.doFinal(text.getBytes()); StringBuilder sb = new StringBuilder(); for (byte b : digest) { sb.append(String.format("%02x", b)); } return sb.toString(); } catch (NoSuchAlgorithmException | InvalidKeyException e) { e.printStackTrace(); return null; } } } ``` 在这个示例中,我们首先定义了一个字符串text和一个密钥key,然后调用hmacSha1方法来获取HMAC-SHA1加密后的结果。在hmacSha1方法中,我们首先使用"javax.crypto.Mac"类获取HmacSHA1算法实例,然后使用密钥初始化该对象。接着,我们调用doFinal方法来计算HMAC-SHA1值,并将结果转换成十六进制字符串返回。 需要注意的是,HMAC-SHA1算法需要一个密钥来进行计算,密钥的长度应该不小于160位(20字节)。在实际应用中,密钥的生成和管理也是非常重要的,需要特别注意。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值