C语言实现SHA-1

参考:《密码学引论》第二版 武汉大学出版社

SHA-1简介

SHA-1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。(源自百度百科)

具体实现

数据填充
填充数据的母的是使数据长度与448模512同余(这里是指位数)。若数据本身已经满足上述长度要求,让需要进行填充(例如,若数据长度为448位,则仍需要填充512位使其长度变为960,原因最后一组填充需要在数据后附加一个1(8位)以及填充前数据的长度(64位),因此最后一组长度最长为440(输入为字符串格式下)),因此填充位数在1~512之间。

填充方法为在数据后附加一个1和若干个0,然后附上表示填充前数据长度的64位数据(最高有效位在前)。
以"this is a test"为例:
填充前:
在这里插入图片描述
填充后(0x70表示输入字符串的位数):
在这里插入图片描述
其他情况详见代码

初始化缓冲区
Hash函数中间结果和最终结果都保存于160位的缓冲区中,缓冲区由5个32位寄存器组成,将这些寄存器初始化为下列32为的整数值。

unsigned int h[5]={0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0};

需要注意的是,在SHA-1中,字的最高有效字节存于低地址字节位置。

执行算法主循环
如图所示:
在这里插入图片描述
每次循环处理一个512位的分组,故循环次数位填充后的数据分组数。

具体代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h> 
#define rol(x,y) ((x<<y)|(x>>(32-y)))  //循环左移 

//一次循环过程,str为填充后的数据或是数据中的一部分 
void round(unsigned char str[64],unsigned int h[5]){
	unsigned int a, b, c, d, e,tmp,w[80];
	unsigned int i;
	for(i=0;i<16;i++){
		w[i]=((unsigned int)str[i*4]<<24)|(((unsigned int)str[i*4+1])<<16)|
						(((unsigned int)str[i*4+2])<<8)|(((unsigned int)str[i*4+3])<<0);
	}
	for (i=16;i<80;i++ ){
		tmp = w[i-3]^w[i-8]^w[i-14]^w[i-16];
		w[i]=rol(tmp,1);
    }
    
    a=h[0];b=h[1];c=h[2];d=h[3];e=h[4];
    for(i=0;i<80;i++){
    	switch(i/20){
    		case 0:tmp=rol(a,5)+((b&c)|(d&~b))+e+w[i]+0x5a827999;break;
    		case 1:tmp=rol(a,5)+(b^c^d)+e+w[i]+0x6ed9eba1;break;
    		case 2:tmp=rol(a,5)+((b&c)|(b&d)|(c&d))+e+w[i] +0x8f1bbcdc;break;
    		case 3:tmp=rol(a,5)+(b^c^d)+e+w[i] + 0xca62c1d6;break;
		}
		e=d;d=c;
		c=rol(b,30);
		b=a;a=tmp;
	}
	h[0]+=a;h[1]+=b;h[2]+=c;h[3]+=d;h[4]+=e;
}

//sha-1算法 
void sha1(unsigned char*input,long long len,unsigned char*output){
	unsigned char temp[64];
	unsigned int h[5]={0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0};
	unsigned int i,n=len,tmp;
	while(n>=64){
		memcpy(temp,input+len-n,64);
		round(temp,h);
		n-=64;
	}
	
	if(n>=56){
		memset(temp,0,64);
		memcpy(temp,input+len-n,n);temp[n]=128;
		round(temp,h);
		memset(temp,0,64);
		for(i=56;i<64;i++)
			temp[i]=((len*8)>>(63-i)*8)&0xff;
		round(temp,h);
	}
	else{
		memset(temp,0,64);
		memcpy(temp,input+len-n,n);temp[n]=128;
		for(i=56;i<64;i++)
			temp[i]=((len*8)>>(63-i)*8)&0xff;
		round(temp,h);	
	}
	
	for(i=0;i<20;i++){
		tmp=(h[i/4]>>((3-i%4)*8))&0xff;
		sprintf((char*)output+2*i,"%02x",tmp);
	}
}

//测试 
int main(){
	unsigned char input[]="this is a test aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",output[40]={0};
	sha1(input,strlen((char*)input),output);
	printf("%s\n",output);
}

代码效果:
在这里插入图片描述
在线工具网址:http://ctf.ssleye.com/hash.html
工具求hash结果:

在这里插入图片描述

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值