安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 SHA1有如下特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要。
SHA1算法描述
由于sha1算法是针对位进行操作,所以,我们必须把原始信息以二进制串来保存起来,由于C++中没有byte类型,我们可以用string来代替.假设我们要求的原始数据为"123456",那么它的二进制表示即为:
00011111 00100000 00100001 00100010 00100011 00100100
为了方便表示,通常用16进制来表示:
31 32 33 34 35 36
这个字串共有6个字符,每个字符占8位,所以原始数据的长度即为6*8=48,下面来进行sha1计算.
1.补位
进行sha1算法加密前需要先对原始数据加工,加工的第一步就是补位,补位的策略是:先给数据后面添加一个'1'(所说的添加均是指在二进制下面添加,因为sha1加密是针对位操作.),然后再在后面添加'0',使得添加后数据长度模512后余448. 在本例中,原始数据为48,添加一个'1'后为49,则需要添加399个'0'. 添加后原始数据的16进制表示应该为以下所示:
31323334 35368000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000
进行补位的代码:
2.写入长度
sha1加密算法的操作对象是位,操作单位是块,一个分块为512位,所以在加密前要把原始数据补为512的倍数,在第一步中我们已经把数据补为模512余448,再在后面补上一个64位数来表示原始数据长度,64+448刚好为512,满足加密要求. 补上长度后数据的16进制表示应该为:
31323334 35368000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000030
写入长度的代码:
3.定义所需函数
为了使得不同的原始数据产生不同的结果,sha1使用了四个(3种)非线性函数来计算:
B,C,D为数据,t为当前进行的加密步骤.每个步骤下的函数为:
(0<=t<20):f(B,C,D,t)=(B & C) | ((~B) & D);
(20<=t<40):f(B,C,D,t)=B ^ C ^ D;
(40<=t<60):f(B,C,D,t)=(B & C) | ((B & D) | (C & D));
(60<=t<80):f(B,C,D,t)=B ^ C ^ D;
此外,sha1加密还需要进行循环移位计算,代码实现如下:
4.计算消息摘要
进行完所有的预处理,就可以计算sha1了,计算需要用到4个关键常量K[4],5+1个字缓冲,分别为A,B,C,D,E,T.还有最大的,进行数据运算的80字缓冲区W[80],它们的定义如下:
加密过程是这样进行的:
1.取出第一块512位的数据,因为我们用字节来存储,就是取64个字节.
2.以每32位分块,分为16块,放在字缓冲W[0]~W[15]中.
3.将80字缓冲W的后64字填充.填充策略为:W[t]=circleShift(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16],1);
4.填充完毕,从W[0]开始,进行80轮的加密计算.
5.为5个字缓冲区A,B,C,D,E加上它们的原始数据.
6.如果没有处理完,则取下一个512字节的分块,执行步骤2,若处理完,A,B,C,D,E即为sha1加密结果,将它们以16进制表示,此字串就是sha1信息摘要串,即sha1密码.
对于我们的测试数据,sha1("123456") 结果应该为:"7c4a8d09ca3762af61e59520943dc26494f8941b"