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结果: