本文参考国标文件GB/T 32905——2016,重点在于对示例的计算。
1 范围
本标准规定了SM3密码杂凑算法的计算方法和计算步骤,并给出了运算示例。
本标准适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。
2 术语和定义
下列术语和定义适用于本文将。
2.1 比特串 bit string
具有0或1值的二进制数字序列。
2.2 大端 big-endian
数组在内存中的一种表示格式,规定左边为高有效位,右边为低有效位。即数的高阶字节放在存储器的低地址,数的低阶字节放在存储器的高地址。
2.3 消息 message
任意有限长度的比特串,本标准中消息作为杂凑算法的输入数据。
2.4 杂凑值 hash value
杂凑算法作用于一条消息时输出的消息摘要(比特串)。
2.5 字 word
长度为32比特的组(串)。
3 符号
下列符号适用于本文件。
A B C D E F G H ABCDEFGH ABCDEFGH:8个字寄存器或它们的值的串连
B ( i ) B_{(i)} B(i):第 i i i个消息分组
C F CF CF:压缩函数
F F j {FF}_j FFj:布尔函数,随 j j j的变化取不同的表达式
G G j {GG}_j GGj:布尔函数,随 j j j的变化取不同的表达式
I V IV IV:初始值,用于确定压缩函数寄存器的初态
P 0 P_0 P0:压缩函数中的置换函数
P 1 P_1 P1:消息扩展中的置换函数
T j T_j Tj:算法常量,随 j j j的变化取不同的值
m m m:消息
m ′ {m}' m′:填充后的消息
m o d mod mod:模运算
n n n:消息分组个数
∧ \wedge ∧:32比特与运算
∨ \vee ∨:32比特或运算
⊕ \oplus ⊕:32比特异或运算
¬ \neg ¬:32比特非运算
+ + +:mod 2 32 2^{32} 232比特算术加运算
< < < k <<<k <<<k:32比特循环左移 k k k比特运算
← \gets ←:左向赋值运算符
4 常数与函数
4.1 初始值
$IV=$7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e
4.2 常量
T j = { 79cc4519 0 ≤ j ≤ 15 7a879d8a 16 ≤ j ≤ 63 T_j=\begin{cases} & \text{ 79cc4519 } \quad 0\le j\le 15 \\ & \text{ 7a879d8a } \quad 16\le j \le 63 \end{cases} Tj={ 79cc4519 0≤j≤15 7a879d8a 16≤j≤63
4.3 布尔函数
F F j ( X , Y , Z ) = { X ⊕ Y ⊕ Z 0 ≤ j ≤ 15 ( X ∧ Y ) ∨ ( X ∧ Z ) ∨ ( Y ∧ Z ) 16 ≤ j ≤ 63 {FF}_j(X,Y,Z)=\begin{cases} &{X \oplus Y \oplus Z} \quad 0 \le j\le15 \\ &{(X \wedge Y)\vee(X \wedge Z)\vee(Y \wedge Z)} \quad 16 \le j \le 63 \end{cases} FFj(X,Y,Z)={X⊕Y⊕Z0≤j≤15(X∧Y)∨(X∧Z)∨(Y∧Z)16≤j≤63
G G j ( X , Y , Z ) = { X ⊕ Y ⊕ Z 0 ≤ j ≤ 15 ( X ∧ Y ) ∨ ( ¬ X ∧ Z ) 16 ≤ j ≤ 63 {GG}_j(X,Y,Z)=\begin{cases} &{X \oplus Y \oplus Z} \quad 0 \le j\le15 \\ &{(X \wedge Y)\vee(\neg X \wedge Z)} \quad 16 \le j \le 63 \end{cases} GGj(X,Y,Z)={X⊕Y⊕Z0≤j≤15(X∧Y)∨(¬X∧Z)16≤j≤63
其中 X , Y , Z X,Y,Z X,Y,Z为字。
例: X = X= X= 7380166F, Y = Y= Y= 4914B2B9, Z = Z= Z= 172442D7
当 0 ≤ j ≤ 15 0 \le j \le 15 0≤j≤15时:
F F j ( X , Y , Z ) = X ⊕ Y ⊕ Z = {FF}_j(X,Y,Z)=X \oplus Y \oplus Z= FFj(X,Y,Z)=X⊕Y⊕Z= (7380166F) ⊕ \oplus ⊕ (4914B2B9) ⊕ \oplus ⊕ (172442D7) = = = 2DB0E601
G G j ( X , Y , Z ) = X ⊕ Y ⊕ Z = {GG}_j(X,Y,Z)=X \oplus Y \oplus Z= GGj(X,Y,Z)=X⊕Y⊕Z= (7380166F) ⊕ \oplus ⊕ (4914B2B9) ⊕ \oplus ⊕ (172442D7) = = = 2DB0E601
当 16 ≤ j ≤ 63 16 \le j \le 63 16≤j≤63时:
F F j ( X , Y , Z ) = ( X ∧ Y ) ∨ ( X ∧ Z ) ∨ ( Y ∧ Z ) = ( 7380166 F ∧ 4914 B 2 B 9 ) ∨ ( 7380166 F ∧ 172442 D 7 ) ∨ ( 4914 B 2 B 9 ∧ 172442 D 7 ) = ( 41001229 ) ∨ ( 13000247 ) ∨ ( 01040291 ) = 530412 F F {FF}_j(X,Y,Z)={(X \wedge Y)\vee(X \wedge Z)\vee(Y \wedge Z)}={(7380166F \wedge 4914B2B9)\vee(7380166F \wedge 172442D7)\vee(4914B2B9 \wedge 172442D7)}=(41001229)\vee (13000247) \vee (01040291)= 530412FF FFj(X,Y,Z)=(X∧Y)∨(X∧Z)∨(Y∧Z)=(7380166F∧4914B2B9)∨(7380166F∧172442D7)∨(4914B2B9∧172442D7)=(41001229)∨(13000247)∨(01040291)=530412FF
G G j ( X , Y , Z ) = ( X ∧ Y ) ∨ ( ¬ X ∧ Z ) = ( 7380166 F ∧ 4914 B 2 B 9 ) ∨ ( ¬ 7380166 F ∧ 172442 D 7 ) = ( 41001229 ) ∨ ( 8 C 7 F E 990 ∧ 172442 D 7 ) = ( 41001229 ) ∨ ( 04244090 ) = 452452 B 9 {GG}_j(X,Y,Z)={(X \wedge Y)\vee(\neg X \wedge Z)}={(7380166F \wedge 4914B2B9)\vee(\neg 7380166F \wedge 172442D7)}=(41001229) \vee(8C7FE990 \wedge 172442D7)=(41001229) \vee(04244090)=452452B9 GGj(X,Y,Z)=(X∧Y)∨(¬X∧Z)=(7380166F∧4914B2B9)∨(¬7380166F∧172442D7)=(41001229)∨(8C7FE990∧172442D7)=(41001229)∨(04244090)=452452B9
4.4 置换函数
P 0 ( X ) = X ⊕ ( X < < < 9 ) ⊕ ( X < < < 17 ) P_0(X)=X \oplus (X<<<9) \oplus (X<<<17) P0(X)=X⊕(X<<<9)⊕(X<<<17)
P 1 ( X ) = X ⊕ ( X < < < 15 ) ⊕ ( X < < < 23 ) P_1(X)=X \oplus (X<<<15) \oplus (X<<<23) P1(X)=X⊕(X<<<15)⊕(X<<<23)
其中 X X X为字。
例:
P 0 ( 7380166 F ) = 7380166 F ⊕ ( 002 C D E E 7 ) ⊕ ( 2 C D E E 700 ) = 5 F 722 F 88 P_0(7380166F)=7380166F \oplus (002CDEE7) \oplus (2CDEE700)=5F722F88 P0(7380166F)=7380166F⊕(002CDEE7)⊕(2CDEE700)=5F722F88
P 1 ( 7380166 F ) = 7380166 F ⊕ ( 0 B 37 B 9 C 0 ) ⊕ ( 37 B 9 C 00 B ) = 4 F 0 E 6 F A 4 P_1(7380166F)=7380166F \oplus (0B37B9C0) \oplus (37B9C00B)=4F0E6FA4 P1(7380166F)=7380166F⊕(0B37B9C0)⊕(37B9C00B)=4F0E6FA4
5 算法描述
5.1 概述
SM3密码杂凑算法的输入为长度为 l ( l < 2 64 ) l(l<2^{64}) l(l<264)比特的消息 m m m,经过填充、迭代压缩,生成杂凑值,杂凑值输出长度为256比特。
5.2 填充
假设消息 m m m的长度为 l l l比特,则首先将比特“1”添加到消息的末尾,再添加 k k k个“0”, k k k是满足 l + 1 + k ≡ 448 ( m o d 512 ) l+1+k\equiv 448(mod \quad 512) l+1+k≡448(mod512)的最小的非负整数。然后添加一个64位比特串,该比特串是长度 l l l的二进制表示。填充后的消息 m ′ {m}' m′的比特长度为512的倍数。
例如:对消息:01100001 01100010 01100011,其长度 l = 24 l=24 l=24,经填充得到比特串:
5.3 迭代压缩
5.3.1 迭代过程
将填充后的消息 m ′ {m}' m′按512比特进行分组: m ′ = B ( 0 ) B ( 1 ) ⋅ ⋅ ⋅ B ( n − 1 ) {m}'=B^{(0)}B^{(1)}\cdot \cdot \cdot B^{(n-1)} m′=B(0)B(1)⋅⋅⋅B(n−1),其中 n = ( l + k + 65 ) / 512 n=(l+k+65)/512 n=(l+k+65)/512。
对 m ′ {m}' m′按下列方式迭代:
其中 C F CF CF是压缩函数, V ( 0 ) V^{(0)} V(0)为256比特初始值 I V IV IV, B ( i ) B^{(i)} B(i)为填充后的消息分组,迭代压缩结果为 V ( n ) V^{(n)} V(n)。
5.3.2 消息扩展
将消息分组 B ( i ) B^{(i)} B(i)按以下方法扩展生成132个消息字 W 0 , W 1 , ⋅ ⋅ ⋅ W 67 , W 0 ′ , W 1 ′ , ⋅ ⋅ ⋅ W 63 ′ W_0,W_1,\cdot \cdot \cdot W_{67},{W_0}',{W_1}',\cdot \cdot \cdot {W_{63}}' W0,W1,⋅⋅⋅W67,W0′,W1′,⋅⋅⋅W63′,用于压缩函数 C F CF CF:
第一步,将消息分组 B ( i ) B^{(i)} B(i)划分为16个字 W 0 , W 1 , ⋅ ⋅ ⋅ W 15 W_0,W_1,\cdot \cdot \cdot W_{15} W0,W1,⋅⋅⋅W15。
第二步,
F O R j = 16 T o 67 FOR \quad j=16 \quad To \quad 67 FORj=16To67
W j ← P 1 ( W j − 16 ⊕ W j − 9 ⊕ ( W j − 3 < < < 15 ) ) ⊕ ( W j − 13 < < < 7 ) ⊕ W j − 6 E N D F O R \quad \quad W_j \gets P_1(W_{j-16}\oplus W_{j-9} \oplus (W_{j-3}<<<15))\oplus (W_{j-13}<<<7) \oplus W_{j-6} \quad ENDFOR Wj←P1(Wj−16⊕Wj−9⊕(Wj−3<<<15))⊕(Wj−13<<<7)⊕Wj−6ENDFOR
第三步,
F O R j = 0 T O 63 FOR \quad j=0 \quad TO \quad 63 FORj=0TO63
W j ′ = W i ⊕ W i + 4 \quad \quad {W_j}'=W_i \oplus W_{i+4} Wj′=Wi⊕Wi+4
E N D F O R ENDFOR ENDFOR
例: B 0 = B^0= B0= 61626380 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000018
W 16 ← P 1 ( W 0 ⊕ W 7 ⊕ ( W 3 < < < 15 ) ) ⊕ ( W 3 < < < 7 ) ⊕ W 10 = P 1 ( 61626380 ) = 9092 E 200 W_{16} \gets P_1(W_0 \oplus W_7 \oplus (W_3<<<15)) \oplus (W_3<<<7) \oplus W_{10}=P_1(61626380)=9092E200 W16←P1(W0⊕W7⊕(W3<<<15))⊕(W3<<<7)⊕W10=P1(61626380)=9092E200
其他依次类推。
W 0 ′ = W 0 ⊕ W 4 = 61626380 {W_0}'=W_0 \oplus W_4=61626380 W0′=W0⊕W4=61626380
其他依次类推。
5.3.3 压缩函数
令 A , B , C , D , E , F , G , H A,B,C,D,E,F,G,H A,B,C,D,E,F,G,H为字寄存器, S S 1 , S S 2 , T T 1 , T T 2 SS1,SS2,TT1,TT2 SS1,SS2,TT1,TT2为中间变量,压缩函数 V i + 1 = C F ( V ( i ) , B ( i ) ) , 0 ≤ i ≤ n − 1 V^{i+1}=CF(V^{(i)},B^{(i)}),0 \le i \le n-1 Vi+1=CF(V(i),B(i)),0≤i≤n−1。计算过程描述如下:
A B C D E F G H ← V ( i ) ABCDEFGH \gets V^{(i)} ABCDEFGH←V(i)
F O R j = 0 T o 63 FOR \quad j=0 \quad To \quad 63 FORj=0To63
S S 1 ← ( ( A < < < 12 ) + E + ( T i < < < ( j m o d 32 ) ) ) < < < 7 \quad \quad SS1 \gets((A<<<12)+E+(T_i<<<(j\quad mod32)))<<<7 SS1←((A<<<12)+E+(Ti<<<(jmod32)))<<<7
S S 2 ← S S 1 ⊕ ( A < < < 12 ) \quad \quad SS2 \gets SS1 \oplus (A<<<12) SS2←SS1⊕(A<<<12)
T T 1 ← F F i ( A , B , C ) + D + S S 2 + W i ′ \quad \quad TT1 \gets FF_i(A,B,C)+D+SS2+{W_i}' TT1←FFi(A,B,C)+D+SS2+Wi′
T T 2 ← G G i ( E , F , G ) + H + S S 1 + W i \quad \quad TT2 \gets GG_i(E,F,G)+H+SS1+W_i TT2←GGi(E,F,G)+H+SS1+Wi
D ← C \quad \quad D \gets C D←C
C ← B < < < 9 \quad \quad C\gets B<<<9 C←B<<<9
B ← A \quad \quad B \gets A B←A
A ← T T 1 \quad \quad A \gets TT1 A←TT1
H ← G \quad \quad H \gets G H←G
G ← F < < < 19 \quad \quad G \gets F<<<19 G←F<<<19
F ← E \quad \quad F \gets E F←E
E ← P 0 ( T T 2 ) \quad \quad E \gets P_0(TT2) E←P0(TT2)
E N D F O R ENDFOR ENDFOR
V ( i + 1 ) ← A B C D E F G H ⊕ V ( i ) V^{(i+1)}\gets ABCDEFGH \oplus V^{(i)} V(i+1)←ABCDEFGH⊕V(i)
其中,字的存储为大端(big-endian),左边为高有效位,右边为低有效位。
+ + +为十六进制加法。
例: j = j= j= 0 I V = IV= IV= 7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e
S S 1 ← ( ( 7380166 f < < < 12 ) + a 96 f 30 b c + ( 79 c c 4519 < < < ( 0 m o d 32 ) ) ) < < < 7 = 51368692 SS1 \gets((7380166f<<<12)+a96f30bc+(79cc4519<<<(0\quad mod32)))<<<7=51368692 SS1←((7380166f<<<12)+a96f30bc+(79cc4519<<<(0mod32)))<<<7=51368692
S S 2 ← S S 1 ⊕ ( A < < < 12 ) = 505071 A A SS2 \gets SS1 \oplus (A<<<12)=505071AA SS2←SS1⊕(A<<<12)=505071AA
T T 1 ← F F i ( A , B , C ) + D + S S 2 + W i ′ = 2 D B 0 E 601 + d a 8 a 0600 + 505071 A A + 61626380 = B 9 E D C 12 B TT1 \gets FF_i(A,B,C)+D+SS2+{W_i}'=2DB0E601 + da8a0600 + 505071AA + 61626380=B9EDC12B TT1←FFi(A,B,C)+D+SS2+Wi′=2DB0E601+da8a0600+505071AA+61626380=B9EDC12B
T T 2 ← G G i ( E , F , G ) + H + S S 1 + W i = 5 C D 3 E 65 B + b 0 f b 0 e 4 e + 51368692 + 61626380 = C 067 D E B B TT2 \gets GG_i(E,F,G)+H+SS1+W_i=5CD3E65B + b0fb0e4e + 51368692+ 61626380=C067DEBB TT2←GGi(E,F,G)+H+SS1+Wi=5CD3E65B+b0fb0e4e+51368692+61626380=C067DEBB
D ← C = 172442 d 7 D \gets C=172442d7 D←C=172442d7
C ← B < < < 9 = 29657292 C\gets B<<<9=29657292 C←B<<<9=29657292
B ← A = 7380166 f B \gets A=7380166f B←A=7380166f
A ← T T 1 = B 9 E D C 12 B A \gets TT1=B9EDC12B A←TT1=B9EDC12B
H ← G = e 38 d e e 4 d H \gets G=e38dee4d H←G=e38dee4d
G ← F < < < 19 = c 550 b 189 G \gets F<<<19=c550b189 G←F<<<19=c550b189
F ← E = a 96 f 30 b c F \gets E=a96f30bc F←E=a96f30bc
E ← P 0 ( T T 2 ) = B 2 A D 29 F 4 E \gets P_0(TT2)=B2AD29F4 E←P0(TT2)=B2AD29F4
其他依次类推。
5.4 输出杂凑值
A B C D E F G H ← V ( n ) ABCDEFGH\gets V^{(n)} ABCDEFGH←V(n)
输出256比特的杂凑值 y = A B C D E F G H y=ABCDEFGH y=ABCDEFGH。
例:
V 1 = A B C D E F G H ⊕ V 0 = V^1=ABCDEFGH \oplus V^0= V1=ABCDEFGH⊕V0= 66C7F0F4 62EEEDD9 D1F2D46B DC10E4E2 4167C487 5CF2F7A2 297DA02B 8F4BA8E0
6 完整代码
#ifndef _SM3_H_
#define _SM3_H_
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const unsigned int IV[8] = {0x7380166F,0x4914B2B9,0x172442D7,0xDA8A0600,0xA96F30BC,0x163138AA,0xE38DEE4D,0xB0FB0E4E};
const unsigned int T[64] = {0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,
0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,0x79CC4519,
0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,
0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,
0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,
0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,
0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,
0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A,0x7A879D8A};
#endif
#include "sm3.h"
unsigned int FF(unsigned int X,unsigned int Y,unsigned int Z,int j);//布尔函数FF
unsigned int GG(unsigned int X,unsigned int Y,unsigned int Z,int j);//布尔函数GG
unsigned int move(unsigned int data , int length);
unsigned int P0(unsigned int X);
unsigned int P1(unsigned int X);
int PaddingNum(long long l);
unsigned int* inputPadding(char ch[]);
unsigned int * MessagePadding(unsigned int * B);
unsigned int * IteratveCompression(char ch[]);
unsigned int FF(unsigned int X,unsigned int Y,unsigned int Z,int j)
{
if(0<=j && j<=15)
{
return X^Y^Z;
}
else if(16<=j && j<=63)
{
return (X&Y)|(X&Z)|(Y&Z);
}
}
unsigned int GG(unsigned int X,unsigned int Y,unsigned int Z,int j)
{
if(0<=j && j<=15)
{
return X^Y^Z;
}
else if(16<=j && j<=63)
{
return (X&Y)|(~X&Z);
}
}
unsigned int move(unsigned int data , int length)
{
unsigned int result = 0;
result = (data << length) ^ (data >> (32-length));
return result;
}
unsigned int P0(unsigned int X)
{
return X^move(X,9)^move(X,17);
}
unsigned int P1(unsigned int X)
{
return X^move(X,15)^move(X,23);
}
int PaddingNum(long long l)
{
int k=-1,i=0;
while (k<0)
{
k = 512*i+447-l;
i++;
if(k>=0)
break;
}
return k;
}
unsigned int* inputPadding(char m[])
{
long long l = strlen(m)*8; //输入的消息的位数
int k=PaddingNum(l);
int len = (l+1+k+64)/32;//填充后的信息 int类型的个数
unsigned int *paddedInput = (unsigned int *)malloc(len*sizeof(unsigned int));
memset(paddedInput,0,len*4); //设初值为0
//将原消息放到扩展信息中
for (int i = 0; i < l/8; i++)
{
*(paddedInput+(i/4)) ^= *(m+i)<<(24-(i%4)*8);
}
//补充0x80
*(paddedInput+l/32) ^= 0x80<<(24-((l/8)%4)*8);
//在尾部填充长度l
*(paddedInput+len-1) = l;
return paddedInput;
}
unsigned int * MessagePadding(unsigned int * B)
{
unsigned static int W[132] = {0};
for(int i=0;i<16;i++)
{
W[i] = *(B+i);
}
for(int i=16;i<68;i++)
{
W[i]=P1(W[i-16]^W[i-9]^move(W[i-3],15))^move(W[i-13],7)^W[i-6];
}
for(int i=0;i<64;i++)
{
W[68+i] = W[i]^W[i+4];
}
return W;
}
unsigned int * IteratveCompression(char m[])
{
long long l = strlen(m)*8; //输入的消息的位数
int k=PaddingNum(l);
int len = (l+1+k+64)/32;//填充后的信息 int类型的个数
unsigned int * paddedInput = inputPadding(m);
unsigned static int V[8] = {0};
V[0] = IV[0];
V[1] = IV[1];
V[2] = IV[2];
V[3] = IV[3];
V[4] = IV[4];
V[5] = IV[5];
V[6] = IV[6];
V[7] = IV[7];
unsigned int A,B,C,D,E,F,G,H,SS1,SS2,TT1,TT2;
unsigned int Bmes[16] = {0};
for(int i=0;i<len/16;i++)
{
//每个分组都要对ABCDEFGH赋初值
A=V[0];B=V[1];C=V[2];D=V[3];E=V[4];F=V[5];G=V[6];H=V[7];
for(int j=0;j<16;j++)
{
Bmes[j] = *(paddedInput+16*i+j);
}
unsigned int *W = MessagePadding(Bmes);
for(int j=0;j<64;j++)
{
SS1 = move((move(A,12)+E+move(T[j],j%32)),7);
SS2=SS1^move(A,12);
TT1 = FF(A,B,C,j)+D+SS2+W[j+68];
TT2 = GG(E,F,G,j)+H+SS1+W[j];
D=C;
C=move(B,9);
B=A;
A=TT1;
H=G;
G=move(F,19);
F=E;
E=P0(TT2);
}
V[0] = A^V[0];V[1] = B^V[1];V[2] = C^V[2];V[3] = D^V[3];
V[4] = E^V[4];V[5] = F^V[5];V[6] = G^V[6];V[7] = H^V[7];
}
return V;
}
int main()
{
char input[100]="abc";
printf("输入的消息为:\n");
for(int i=0;i<strlen(input);i++)
{
printf("%c",input[i]);
if(i%4==3)
printf(" ");
}
printf("\n输入消息的十六进制为:\n");
for(int i=0;i<strlen(input);i++)
{
printf("%.2x",input[i]);
if(i%4==3)
printf(" ");
}
unsigned int *hash = IteratveCompression(input);
printf("\n所得的十六进制杂凑值为:\n");
for(int i=0;i<8;i++)
{
printf("%.8x ",*(hash+i));
}
return 0;
}