SHA1算法详解
0x00 前言
SHA1算法也是哈希算法的一种,只要理解了MD5算法,SHA1也很快就能理解。
MD5算法可以参考:MD5算法详解
MD5算法得出的MD5值长度为16个字节(8*16=128位)
SHA1算法得出的SHA1值长度为20个字节(8*20=160位)
0x01 填充信息
和MD5算法类似,对信息的第一步也是填充信息直至满足条件。
填充的过程如下:
1.先判断文件(消息)的大小(长度) mod 512 == 448 mod 512 ,就是大小(长度)对512求余等于448。(这里的512、448是“位”为单位,转成“字节”就是64、56,即mod 64 == 56 mod 64)
2.如果大小(长度)满足 mod 512 == 448 mod 512,就在文件(消息)的末尾处添加64位(8字节)的值,值的内容是原消息的长度(以位为单位)
3.如果大小(长度)不满足要求,就执行以下操作:
(1)填充1个1
(2)填充0,直到满足满足过程的第一步。
注意:这里是以位为单位,假如是以字节为单位,第一个填充的是0x80(1000 0000),然后就填0x0
举例:消息内容为“gnubd”,就能得到以下内容
67 6E 62 75 64 80 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28
还需要注意到的是最后原消息的长度是以大端存储的方式存到内存中的,这里与MD5的存储是有区别的。
0x02 数据说明
这里列举出所用到的数据
DWORD sha1::A = 0x67452301;
DWORD sha1::B = 0xEFCDAB89;
DWORD sha1::C = 0x98BADCFE;
DWORD sha1::D = 0x10325476;
DWORD sha1::E = 0xC3D2E1F0;
这里相对MD5算法多了4个字节。(因为SHA1值就是比MD5值多4个字节嘛)
常量:
DWORD sha1::k[4] = {0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
MD5就有64个,这个就简单一点,4个
0x03 处理信息
和MD5算法类似,也是需要将消息分组,每64个字节(512位)一组,分成多个组(n个)。
对与每一组(0 < i <= n)都要做如下处理。
将64个字节分成16组-,每组刚好4个字节
然后生成-,生成的方法如下:
for(DWORD i = 16;i<80;i++){
DWORD temp = w[i-3]^w[i-8]^w[i-14]^w[i-16];
w[i] = temp<<1 | temp>>31;
}
接下来就是做核心运算了。
将a、b、c、d、e分别赋值为上面的A、B、C、D、E,作为的初始值
然后循环80次,从0-79:
for(DWORD j = 0;j<80;j++){
DWORD temp;
DWORD temp2 = a<<5|a>>27; //循环左移5位,等下需要用到
switch(j/20){
case 0: //0-19步执行这里
temp = (b&c)|((~(b))&d);
temp += sha1::k[0]; //这个是常数
break;
case 1: //20-39步执行这里
temp = (b^c^d);
temp += sha1::k[1];
break;
case 2: //40-59步执行这里
temp = (b&c)|(b&d)|(c&d);
temp += sha1::k[2];
break;
case 3: //60-79步执行这里
temp = (b^c^d);
temp += sha1::k[3];
break;
}
temp += temp2 + e + w[j]; //这里就是上面生成的80个分组了
e = d;
d = c;
c = b<<30 | b>>2; //循环左移30位
b = a;
a = temp;
}
A+=a;
B+=b;
C+=c;
D+=d;
E+=e;
注意最后这里和MD5类似,也是再将abcde分别加上初始值ABCDE,作为下一个消息分组的初始值,直到最后一个分组计算完后,得出的结果就是SHA1值。
即:
这里只需按直接输出就好了,不必像md5那样调整字节位置后再输出,
上一篇: 数字签名算法DSA
下一篇: 原代码审计笔记-安全缺陷