sha1 加密算法的 C++ 语言实现 - sbw Blog

sha1 加密算法的 C++ 语言实现

来源: 石博文博客 | 浏览: 22658 | 评论: 12 发表时间: 2013-06-19

安全哈希算法(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"


sha1加密计算原理示意图

完整的C++语言实现代码



  • 声明: 评论属于其发表者所有,不代表本站的观点和立场.
  • 222s 回复该留言 时间: 2013-12-10

    你的源码在VS2008下运行"123456"的加密结果和你给出的结果(也是用其他工具可得到的正确结果)不一致

  • Bing 回复该留言 时间: 2013-12-11

    找到错误了,在代码的第37行,strRaw.size()返回的类型是size_t,是32位的,而却对它最高移了56位,而对32位无符号数左移56位,只能得到0,而不是32位无符号数的最高位。而所以导致最后一个512 bit块接长度时,长度永远落在最后四个字节。改正方法(VC下):将strRaw.size()换成((unsigned __int64)strRaw.size())。

  • 石博文 回复该留言 时间: 2013-12-11

    没错,这里是有点问题....因为我的环境是64位的所以结果是正确的....

  • 婷婷 回复该留言 时间: 2014-10-11

    您好! sha1 加密算法完整的C++语言实现代码是删了吗?能不能给我发下啊?我昨天还看到的。[color: Red][/color][b][/b]

  • 路人甲 回复该留言 时间: 2016-10-23

    你好,刚测试代码,发现字节数大于56的时候就跳不出循环了,只能处理56字节以下的消息

  • 石博文 回复该留言 时间: 2016-10-28

    有的呀,是你的浏览器没有加载完成吧:)

已有 6 位网友发表了一针见血的评论,你还等什么?
  • 昵称: *
  • 邮箱:
  • 网址:
  • 记住我的信息
  • Color
  • Red
  • Blue
  • Code
  • bash
  • cpp
  • css
  • java
  • js
  • perl
  • php
  • python
  • ruby
  • sql
  • xml