Hash散列算法详细解析(四)

 

关键词SHA-0    SHA-1    SHA224    SHA256    SHA384                                          

 

      SHA系列Hash算法是由美国国家安全局(US National Security Agency)设计的。完整的说,SHA共有6个标准。分别是:SHA-0(1992年)、SHA-1(1995年)、SHA224(2002年)、SHA256(2000年)、SHA-384(2000年)和SHA-512(2000年)。关于SHA算法最权威的文档当属FIPS P180系列,最新的是2002年修订的FIPS P180-2。参考地址为:http://csrc.nist.gov/publications/.
      SHA的具体描述大家自己去下载文档来看就行了。SHA与普通Hash算法最大的不同在于它不是专门为Intel cpu设计的,所以,其整数的表示方式和Intel cpu目前的低字节在前的方法不一样。以下只列出了SHA-1算法的代码。附件里面有所有标准(除了已经被淘汰的SHA-0)的代码。

//sha-1,224,256,384,512
//program by Goodzzp
//2005.10.13

//Notice:
// this sha.h file referred crypto++5.21 and SHA standard(Federal Information
// Processing Standards Publication 180-2 with SHA224 notice) 2002 Auguest 1

#include "define.h"


//....beigin sha-1
#define sha_blk0(i) (W[i] = m_data[i])
#define sha_blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))

#define sha_f1(x,y,z) (z^(x&(y^z)))
#define sha_f2(x,y,z) (x^y^z)
#define sha_f3(x,y,z) ((x&y)|(z&(x|y)))
#define sha_f4(x,y,z) (x^y^z)

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define sha_R0(v,w,x,y,z,i) z+=sha_f1(w,x,y)+sha_blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R1(v,w,x,y,z,i) z+=sha_f1(w,x,y)+sha_blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R2(v,w,x,y,z,i) z+=sha_f2(w,x,y)+sha_blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R3(v,w,x,y,z,i) z+=sha_f3(w,x,y)+sha_blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R4(v,w,x,y,z,i) z+=sha_f4(w,x,y)+sha_blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);


//sha1 algorithm
class SHA1
{
public:
 //输出结果的长度(字节)
 static UI32 OutDataLength()
 {
  return 4*5;
 }
 //SHA-1变换函数
 //out:输出,长度为20,要求事先已经分配了内存
 //in:输入
 //length:输入值的长度
 void Hash(UI8 *out,const UI8 *in,UI32 length)
 {
  UI32 i = length>>6,j=(length&0x3f),k;
  //对数据64 64个字节的计算
  for(k=0;k  {
   StepTransform((UI8 *)(in + k * 64),64,length);
  }
  //最后计算尾数
  StepTransform((UI8 *)(in + 64 * i),j,length);
  //拷贝输出
  for(i=0;i<4;i++) //反转
  {
   m_state[i] = ((m_state[i]&0xff) << 24) | ((m_state[i]&0xff00) << 8) |
    ((m_state[i]&0xff0000) >> 8) | ((m_state[i]&0xff000000)>>24);
  }
  memcpy(out,m_state,4*5);
  
  //恢复m_state值
  m_state[0] = 0x67452301L;
  m_state[1] = 0xEFCDAB89L;
  m_state[2] = 0x98BADCFEL;
  m_state[3] = 0x10325476L;
  m_state[4] = 0xC3D2E1F0L;  
 }
 SHA1() //initialize data
 {
  m_state[0] = 0x67452301L;
  m_state[1] = 0xEFCDAB89L;
  m_state[2] = 0x98BADCFEL;
  m_state[3] = 0x10325476L;
  m_state[4] = 0xC3D2E1F0L;  
 }
private:
 //每步的变换函数
 //输入:
 //  data:   要处理的数据块(不大于64字节)
 //  dataBlockLen: 数据块的长度
 //  dataTotalLen: 要处理的所有数据块的总长度
 //输出结果保存在m_state里面
 void StepTransform(UI8 *data,UI32 dataBlockLen, UI32 dataTotalLen)
 {
  UI8 buffer[64];
  UI32 len=dataTotalLen*8;
  
  memset(buffer,0,64);//清空数据为0
  memcpy(buffer,data,dataBlockLen);//拷贝数据到缓冲
  
  if(dataBlockLen <64) //需要增加数据
  {
   if(dataBlockLen<56)//当前数据是最后若干个,而且不需要增加一次变换
   {
    //添加1和0
    buffer[dataBlockLen]=0x80;
    //添加长度
    buffer[63]=(UI8)(len&0xff);
    len>>=8;
    buffer[62]=(UI8)(len&0xff);
    len>>=8;
    buffer[61]=(UI8)(len&0xff);
    len>>=8;
    buffer[60]=(UI8)(len&0xff);
    //变换
    FirstTransform((UI32*)buffer);
    CoreTransform();
   }
   else if(dataBlockLen>=56)
   {
    //添加1和0
    buffer[dataBlockLen]=0x80;
    //变换
    FirstTransform((UI32*)buffer);
    CoreTransform();
    //添加长度
    memset(buffer,0,64);
    buffer[63]=(UI8)(len&0xff);
    len>>=8;
    buffer[62]=(UI8)(len&0xff);
    len>>=8;
    buffer[61]=(UI8)(len&0xff);
    len>>=8;
    buffer[60]=(UI8)(len&0xff);
    //变换
    FirstTransform((UI32*)buffer);
    CoreTransform();
   }
  }
  else if(dataBlockLen == 64)
  {
   //变换
   FirstTransform((UI32*)buffer);
   CoreTransform();
  }
 }

 //把64字节的原始数据data进行初步转化到m_data中去
 void FirstTransform(UI32 *data)
 {
  //拷贝
  memcpy(m_data,data,64);
  //反转,因为sha-1是低位在后面的存储方法,所以,需要把abcd efgh变成dcba hgfe。
  for(UI32 i=0;i<16;i++)
  {
   m_data[i] = ((m_data[i]&0xff) << 24) | ((m_data[i]&0xff00) << 8) |
    ((m_data[i]&0xff0000) >> 8) | ((m_data[i]&0xff000000)>>24);
  }
  //根据这16个生成其它64个UI32
  for(UI32 j=16;j<80;j++)
  {
   m_data[j] = rotlFixed(m_data[j-3]^m_data[j-8]^m_data[j-14]^m_data[j-16],1);
  }
 }
 
 //核心变换
 void CoreTransform()
 {
  UI32 W[16];
  UI32 a = m_state[0];
  UI32 b = m_state[1];
  UI32 c = m_state[2];
  UI32 d = m_state[3];
  UI32 e = m_state[4];
  /* 4 rounds of 20 operations each. Loop unrolled. */
  sha_R0(a,b,c,d,e, 0); sha_R0(e,a,b,c,d, 1); sha_R0(d,e,a,b,c, 2); sha_R0(c,d,e,a,b, 3);
  sha_R0(b,c,d,e,a, 4); sha_R0(a,b,c,d,e, 5); sha_R0(e,a,b,c,d, 6); sha_R0(d,e,a,b,c, 7);
  sha_R0(c,d,e,a,b, 8); sha_R0(b,c,d,e,a, 9); sha_R0(a,b,c,d,e,10); sha_R0(e,a,b,c,d,11);
  sha_R0(d,e,a,b,c,12); sha_R0(c,d,e,a,b,13); sha_R0(b,c,d,e,a,14); sha_R0(a,b,c,d,e,15);
  sha_R1(e,a,b,c,d,16); sha_R1(d,e,a,b,c,17); sha_R1(c,d,e,a,b,18); sha_R1(b,c,d,e,a,19);
  sha_R2(a,b,c,d,e,20); sha_R2(e,a,b,c,d,21); sha_R2(d,e,a,b,c,22); sha_R2(c,d,e,a,b,23);
  sha_R2(b,c,d,e,a,24); sha_R2(a,b,c,d,e,25); sha_R2(e,a,b,c,d,26); sha_R2(d,e,a,b,c,27);
  sha_R2(c,d,e,a,b,28); sha_R2(b,c,d,e,a,29); sha_R2(a,b,c,d,e,30); sha_R2(e,a,b,c,d,31);
  sha_R2(d,e,a,b,c,32); sha_R2(c,d,e,a,b,33); sha_R2(b,c,d,e,a,34); sha_R2(a,b,c,d,e,35);
  sha_R2(e,a,b,c,d,36); sha_R2(d,e,a,b,c,37); sha_R2(c,d,e,a,b,38); sha_R2(b,c,d,e,a,39);
  sha_R3(a,b,c,d,e,40); sha_R3(e,a,b,c,d,41); sha_R3(d,e,a,b,c,42); sha_R3(c,d,e,a,b,43);
  sha_R3(b,c,d,e,a,44); sha_R3(a,b,c,d,e,45); sha_R3(e,a,b,c,d,46); sha_R3(d,e,a,b,c,47);
  sha_R3(c,d,e,a,b,48); sha_R3(b,c,d,e,a,49); sha_R3(a,b,c,d,e,50); sha_R3(e,a,b,c,d,51);
  sha_R3(d,e,a,b,c,52); sha_R3(c,d,e,a,b,53); sha_R3(b,c,d,e,a,54); sha_R3(a,b,c,d,e,55);
  sha_R3(e,a,b,c,d,56); sha_R3(d,e,a,b,c,57); sha_R3(c,d,e,a,b,58); sha_R3(b,c,d,e,a,59);
  sha_R4(a,b,c,d,e,60); sha_R4(e,a,b,c,d,61); sha_R4(d,e,a,b,c,62); sha_R4(c,d,e,a,b,63);
  sha_R4(b,c,d,e,a,64); sha_R4(a,b,c,d,e,65); sha_R4(e,a,b,c,d,66); sha_R4(d,e,a,b,c,67);
  sha_R4(c,d,e,a,b,68); sha_R4(b,c,d,e,a,69); sha_R4(a,b,c,d,e,70); sha_R4(e,a,b,c,d,71);
  sha_R4(d,e,a,b,c,72); sha_R4(c,d,e,a,b,73); sha_R4(b,c,d,e,a,74); sha_R4(a,b,c,d,e,75);
  sha_R4(e,a,b,c,d,76); sha_R4(d,e,a,b,c,77); sha_R4(c,d,e,a,b,78); sha_R4(b,c,d,e,a,79);
  /* Add the working vars back into context.m_state[] */
  m_state[0] += a;
  m_state[1] += b;
  m_state[2] += c;
  m_state[3] += d;
  m_state[4] += e;
 }

private:
 UI32 m_state[5]; //保存有sha-1输出值
 UI32 m_data[80]; //保存有每步变换时对输入的初始化转化值
};

typedef SHA1 SHA;
//...end sha-1

//...begin sha256


      还有,需要申明的是,作者给出的任何代码都经过基本测试。并不存在剽窃任何人代码的事情。作者的目的是为了做出中国第一个密码学算法库。打算包含所有已经成为标准或者十分流行的散列、加密、签名、检验及身份认证算法。目前已经完成了Hash算法部分。还有AES,RSA等。作者主要的算法和代码参考源是各种标准文件以及crypto++5.21代码库。这个库也是国外的代码库,目前由一个中国人维护。关于SHA方面,crpto++5.21没有包含新的SHA-224,因为这个库比较老了。本文作者实现了目前所有的SHA标准。

 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值