//printf("%02bx",buf[i]);
}//说明:
print_buf函数需要根据所用单片机来实现,主要是观察数据使用,不影响算法,故注释掉。
voidmain()
{
U8xdataInBuff[1024];
U8xdataOutBuff[64];
SHA1_Ctxxdatactx;
U32xdatai;
//printf("\r\nSHA1TestDemo\r\n");
//*******************************SpeedTest*********************************/
//themessageconsistsof"0x5a",itsbytelengthis30KB
for(i=0;i<1024;i++)
InBuff[i]=0x5a;
SHA1_Init(&ctx);
//printf("\r\nSpeedTestBegin!
");
for(i=0;i<30;i++)
SHA1_Process(&ctx,InBuff,1024);
//printf("\r\nSpeedTestFinished!
");
SHA1_Done(&ctx,OutBuff);
//printbuf(OutBuff,20);//theresultsshouldbe2c950fdbababb179b4707e2a74f29a79922e39fe
//****************************ValidityTest1********************************/
//themessagesallconsistof"0x5a",itsbytelengthisfrom1to136
//printf("\r\n\r\nValidityTest1\r\n");
for(i=0;i<136;i++)
InBuff[i]=0x5a;
for(i=1;i<137;i++)
{
SHA1_Hash(InBuff,i,OutBuff);
//printbuf(OutBuff,20);
}
//****************************ValidityTest2********************************/
//Themessageconsistsof"0x5a",itsbytelengthis132,justforexample,hereare4casesto//computeitsmessagedigest,
//andtheresultsallshouldbe729a731566090c14b961f6a12ba22a64fddfb492
//printf("\r\n\r\nValidityTest2");
for(i=0;i<136;i++)
InBuff[i]=0x5a;
//case1
SHA1_Hash(InBuff,132,OutBuff);
//printf("\r\nCase1:
");
//printbuf(OutBuff,20);
//case2
SHA1_Init(&ctx);
SHA1_Process(&ctx,InBuff,1);
SHA1_Process(&ctx,InBuff+1,2);
SHA1_Process(&ctx,InBuff+3,61);
SHA1_Process(&ctx,InBuff+64,3);
SHA1_Process(&ctx,InBuff+67,65);
SHA1_Done(&ctx,OutBuff);
//printf("\r\nCase2:
");
//printbuf(OutBuff,20);
//case3
SHA1_Init(&ctx);
SHA1_Process(&ctx,InBuff,12);
SHA1_Process(&ctx,InBuff+12,43);
SHA1_Process(&ctx,InBuff+55,2);
SHA1_Process(&ctx,InBuff+57,3);
SHA1_Process(&ctx,InBuff+60,71);
SHA1_Process(&ctx,InBuff+131,1);
SHA1_Done(&ctx,OutBuff);
//printf("\r\nCase3:
");
//printbuf(OutBuff,20);
//case4
SHA1_Init(&ctx);
SHA1_Process(&ctx,InBuff,66);
SHA1_Process(&ctx,InBuff+66,11);
SHA1_Process(&ctx,InBuff+77,47);
SHA1_Process(&ctx,InBuff+124,8);
SHA1_Done(&ctx,OutBuff);
//printf("\r\nCase4:
");
//printbuf(OutBuff,20);
//**************************/
while
(1);
}
SHA1.c
#include
#include
#include"SHA1.h"
//SHA1算法参数
U32codeSHA1_H0[5]={0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0};
U32codeSHA1_K[4]={0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6};
//对32比特的变量x循环左移n比特(芯片是大端顺序,因此可直接用U32类型处理)
U32SHA1_ROTL(U32*x,U8n)
{
return((*x)<>(32-n));
}
//U64类型的大数a=a+len*8;即a表示消息的比特长度,这里参数len<=64
voidSHA1_len_add(U32*a,U16len)
{
a[1]+=(len<<3);
if(a[1]<(len<<3))
a[0]+=1;
}
//当前分组已有的消息的字节长度
U8SHA1_block_len(SHA1_Ctx*ctx)
{
return(ctx->count[1]>>3)&0x3f;
}
//每64字节的消息分组,计算最终得到的abcde
voidSHA1_block(SHA1_Ctx*ctx)
{
S8datai,j;
U32xdataSHA1_abcde[5],*W,temp,temp1;
//initializeabcde
memcpy(SHA1_abcde,ctx->hash,20);
//80rounds
for(i=0;i<80;i++)
{
//computeW[i]
W=ctx->wbuf+(i&15);//当前使用的W[i]。
注意:
i%16==i&15
if(i>15)
{
(*W)=(*W)^ctx->wbuf[(i-3)&15]^ctx->wbuf[(i-8)&15]^ctx->wbuf[(i-14)&15];
(*W)=SHA1_ROTL(W,1);
}
//computeT
switch(j=i/20)
{
case0:
temp=((SHA1_abcde[1])&(SHA1_abcde[2]))^((~(SHA1_abcde[1]))&(SHA1_abcde[3]));\\与上面一起
break;
case2:
temp=((SHA1_abcde[1])&(SHA1_abcde[2]))^((SHA1_abcde[1])&(SHA1_abcde[3]))^((SHA1_abcde[2])&(SHA1_abcde[3]));\\与上面一起
break;
default:
temp=(SHA1_abcde[1])^(SHA1_abcde[2])^(SHA1_abcde[3]);
}
temp1=SHA1_abcde[4];
SHA1_abcde[4]=SHA1_abcde[3];
SHA1_abcde[3]=SHA1_abcde[2];
SHA1_abcde[2]=SHA1_ROTL(SHA1_abcde+1,30);
SHA1_abcde[1]=SHA1_abcde[0];
SHA1_abcde[0]=(SHA1_ROTL(SHA1_abcde,5)+temp+SHA1_K[j]+(*W)+temp1);
}
//getctx->hashfornow
for(i=0;i<5;i++)
ctx->hash[i]+=SHA1_abcde[i];
}
//初始化操作
voidSHA1_Init(SHA1_Ctx*ctx)
{
memset(ctx->count,0,8);
memcpy(ctx->hash,SHA1_H0,20);
}
//分次处理连贯的消息
voidSHA1_Process(SHA1_Ctx*ctx,U8*message,U32len)
{
U8datafilllen,leftlen,rightlen;
while(len>0)
{
leftlen=SHA1_block_len(ctx);//目前分组已有字节长度,也即当前消息的填充下标
rightlen=64-leftlen;//剩余字节长度
filllen=lenlen:
rightlen;//实际补充字节长度
memcpy(((U8xdata*)ctx->wbuf)+leftlen,message,filllen);//填充
SHA1_len_add(ctx->count,filllen);//长度加
message+=filllen;
len-=filllen;
if(!
SHA1_block_len(ctx))
SHA1_block(ctx);
}
}
//消息输入完毕,最后结果处理
voidSHA1_Done(SHA1_Ctx*ctx,U8*digest)
{
U8datalen;
len=SHA1_block_len(ctx);//len=消息实际长度%64,其值为0到63,表示剩余字节数
*((U8xdata*)(ctx->wbuf)+len)=0x80;//开始填充
//若消息长度是64字节的整数倍,或若剩余字节数在1和55之间,则只需本分组填充即可;
//若剩余字节数在56和63之间,本分组和下个填充分组都要处理
memset((U8xdata*)(ctx->wbuf)+len+1,0,len<56?
55-len:
63-len);//中间填充0
if(len>55)
{
SHA1_block(ctx);
memset((U8xdata*)ctx->wbuf,0,56);
}
memcpy(ctx->wbuf+14,ctx->count,8);//最后的消息长度填充(8字节)
SHA1_block(ctx);
memcpy(digest,ctx->hash,20);
}
//一次性计算接口
voidSHA1_Hash(U8*message,U32len,U8*digest)
{
SHA1_Ctxxdatactx;
SHA1_Init(&ctx);
SHA1_Process(&ctx,message,len);
SHA1_Done(&ctx,digest);
}