SHA1算法.docx

上传人:b****7 文档编号:8787499 上传时间:2023-02-01 格式:DOCX 页数:13 大小:18.28KB
下载 相关 举报
SHA1算法.docx_第1页
第1页 / 共13页
SHA1算法.docx_第2页
第2页 / 共13页
SHA1算法.docx_第3页
第3页 / 共13页
SHA1算法.docx_第4页
第4页 / 共13页
SHA1算法.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

SHA1算法.docx

《SHA1算法.docx》由会员分享,可在线阅读,更多相关《SHA1算法.docx(13页珍藏版)》请在冰豆网上搜索。

SHA1算法.docx

SHA1算法

 

SHA1算法实现

源码文件:

main.c,SHA1.h,SHA1.c加入工程编译即可

说明:

该SHA1算法是8位单片机(51内核)KeilC51纯软件实现

 

1SHA1算法说明

1.1.源码算法使用方法

算法使用方法如下:

1、将main.c和SHA1.c,SHA1.h加入工程编译即可;

2数据类型定义

typedefunsignedcharU8;

typedefsingedcharS8;

typedefunsignedintU16;

typedefsignedintS16;

typedefunsignedlongU32;

typedefsignedlongS32;

typedefstruct

{U32count[2];

U32hash[5];

U32wbuf[16];

}SHA1_Ctx;

3函数接口说明

SHA1算法包含的函数列表如下:

表31SHA1算法库函数表

函数

描述

voidSHA1_Init(SHA1_Ctx*ctx)

初始化SHA1模块

voidSHA1_Process(SHA1_Ctx*ctx,U8*message,U32len)

分步对消息进行计算

voidSHA1_Done(SHA1_Ctx*ctx,U8*digest)

完成杂凑计算,取结果

voidSHA1_Hash(U8*message,U32len,U8*digest)

一次性输入,计算,取结果

3.1初始化SHA1模块

SHA1_Init初始化SHA1模块

函数原型voidSHA1_Init(SHA1_Ctx*ctx)

参数说明

ctx输入,分步计算的SHA1_Ctx结构体指针

注意事项对一较长消息进行分步杂凑计算时都要首先调用本函数

例程例程见源码。

3.2分步对消息进行计算

SHA1_Process分步对消息进行计算

函数原型voidSHA1_Process(SHA1_Ctx*ctx,U8*message,U32len)

参数说明

ctx输入,分步计算的SHA1_Ctx结构体指针

message输入,当前处理消息的指针

len输入,当前处理消息的字节长度

注意事项可以将很长的待杂凑消息分成几部分,依次循环调用此函数,每次调用时message取当前部分的起始地址

例程例程见源码。

3.3完成杂凑计算,取结果

SHA1_Done完成杂凑计算,取结果

函数原型voidSHA1_Done(SHA1_Ctx*ctx,U8*digest)

参数说明

ctx输入,分步计算的SHA1_Ctx结构体指针

digest输出,杂凑的结果

注意事项1.在调用SHA1_Process函数将待杂凑数据输入完毕后,调用本函数计算最终的杂凑结果

2.由于SHA1的结果是160比特,即20字节,因此digest指向的空间至少应是20字节

例程例程见源码。

3.4一次性输入,计算,取结果

SHA1_Hash一次性输入,计算,取结果

函数原型voidSHA1_Hash(U8*message,U32len,U8*digest)

参数说明

message输入,待处理消息的指针

len输入,待处理消息的字节长度

digest输出,杂凑的结果

注意事项1.调用本函数进行一次性杂凑计算,效果与完整的调用一次“初始化->分步输入杂凑数据计算->完成杂凑计算”相同

2.由于SHA1的结果是160比特,即20字节,因此digest指向的空间至少应是20字节

例程例程见源码。

源码SHA1算法例程(main.c,SHA1.h,SHA1.c)

SHA1.h

#ifndefSHA1_H

#defineSHA1_H

typedefunsignedcharUCHAR;

typedefunsignedintUINT;

typedefunsignedlongULONG;

typedefunsignedshortUSHORT;

typedefunsignedcharU8;

typedefunsignedintU16;

typedefunsignedlongU32;

typedefcharS8;

typedefintS16;

typedeflongS32;

/*typetoholdtheSHA1context*/

typedefstruct

{U32count[2];

U32hash[5];

U32wbuf[16];

}SHA1_Ctx;

voidSHA1_Init(SHA1_Ctx*ctx);

voidSHA1_Process(SHA1_Ctx*ctx,U8*message,U32len);

voidSHA1_Done(SHA1_Ctx*ctx,U8*digest);

voidSHA1_Hash(U8*message,U32len,U8*digest);

#endif

Main.c

#include

#include

#include

#include"SHA1.h"

//voidprintbuf(U8*buf,U32len)

//{

//inti;

//printf("\r\n");

//for(i=0;i

//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=len

len:

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);

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1