一、概览图:
二、分步解析
1.格式化输入
因为SHA1算法只接受位作为输入,所以进行计算前必须把原始消息(比如字符串、文件等)转换成位字符串。比如,对字符串“abc”产生消息摘要,‘a’=97 ‘b’=98 ‘c’=99,先转换成24位的字符串(实际上在嵌入式c中不需要转换):
01100001 01100010 01100011。
2.补位
消息必须进行补位,使其长度在对512取模以后的余数是448,即(补位后的消息长度)%512 = 448。
对消息进行补位时,先在后面补一个1,如果不满足要求,再补0直到满足对512取模余数为448。这就意味着,补位至少补一位(原消息位数为512N+447),最多补512位(原消息位数为512N+448)。
还是以前面的“abc”为例显示补位的过程:
原始信息:
01100001 01100010 01100011
补位第一步,首先补一个1:
01100001 01100010 01100011 1
可以确定的是,如果用一个字节来表示一个字符,补1之后肯定不满足条件,仍需继续补位。
补位第二步,后面补0直到总长度对512取模余数为448,这里补423个0,使总长度达到为448:
01100001 01100010 01100011 1000……00
补位完成后的数据转换为16进制:
61626380 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000
从16进制数据里可以看到,我们也可以直接采用16进制的方式进行补位(原理是一致的,只不过是进制不同),我们先补80,看是否满足长度对64取余的结果为56,不满足则继续补0。
3.附加长度信息
这一步中,要将原始消息(没有进行补位操作之前)的长度(二进制位数)附加到已经补位的消息之后。
通常用一个64位的数据来表示原始消息的长度。如果消息长度不大于2^64,那么第一个字就是0。
补长度的操作以后,整个消息(16进制)如下:
61626380 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000018
注意,这里是64位,上一步补位后的长度是512N+448,这样,512N+448+64=512(N+1),恰好可以被512整除。
4.分组格式化
1).将整个消息Z拆分为N个512位的数据块Y1,Y2,…,Yn;
2).将每一块数据Yn进行拆分,拆分成16个32位的字M[k](k= 0, 1,……15)
3).对每一块数据Yn进行扩充运算,得到N个扩充后的数据块X1,X2,……Xn,Xn的格式为:W[k](k= 0, 1,……79);
其中扩充算法如下:
W t = M t , 当0≤t≤15
W t = ( W t-3 ^ W t-8^ W t-14^ W t-16 ) << 1, 当16≤t≤79
实际代码实现过程中,分组格化工作可以在计算到对应数据块时再进行,这样可以节省内存空间。
5.准备初始值
第一组即X0的W0计算前需要进行初始化,初始化方法如下:
H0 = 0x67452301;
H1 = 0xEFCDAB89;
H2 = 0x98BADCFE;
H3 = 0x10325476;
H4 = 0xC3D2E1F0;
6.单组运算如图:
1).将A、B、C、D、E、t初始化,A=H0、B=H1、C=H2、D=H3、E=H4,t = 0,其中Hn为传入的值;
2).E = D;
3).D = C;
4).C = B<<30;
5).B = A;
6).A = A<<5+ft(B,C,D)+E+Wt+Kt.
其中ft为函数运算其定义如下:
ft(B,C,D) = (B&C)|((~B)&D) ( 0 <= t <= 19);
ft(B,C,D) = BCD (20 <= t <= 39);
ft(B,C,D) = (B&C)|(B&D) OR (C&D) (40 <= t <= 59);
ft(B,C,D) = BCD (60 <= t <= 79);
其中Wt为格式化数据Xn的一个元素。
其中Kt为常量,定义如下:
Kt = 0x5A827999 (0 <= t <= 19)
Kt = 0x6ED9EBA1 (20 <= t <= 39)
Kt = 0x8F1BBCDC (40 <= t <= 59)
Kt = 0xCA62C1D6 (60 <= t <= 79)
7).t++;
8).循环步骤2到6直至t>79;
9).与初始值求和H0=H0+A、H1=H1+B、H2=H2+C、H3=H3+D、H4=H4+E;
10).输出单次计算结果H0、H1、H2、H3、H4;
7.格式化输出
计算完成后以字节形式输出摘要信息。