sha1释义:安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准 (Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。
sha1特点:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要,所以可以用摘要来校验信息是否正确
代码如下所示:
/*
SHA1 算法产出的是160位的摘要 即 32 * 5长度
有五个字(这里为32位)
*/
#include
#include
#define EACH_HADLE_LEN 64//每次处理64字节
#define DWORD unsigned int
char cipher[40] = "\0";//32 * 5 32位表示 8个十六进制
typedef struct sha1_context
{
DWORD length;
DWORD hashRes[5];
unsigned char block[64];//64字节的块
}sha1_context;
DWORD RoLeft(DWORD value,int index)
{
return (value << index) ^ (value >> (32 - index));
}
void SHA1Init(sha1_context *sha1)
{
if(!sha1){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
sha1->length = 0;
sha1->hashRes[0] = 0x67452301;//初始化H[0] H[1] H[2] H[3] H[4]
sha1->hashRes[1] = 0xefcdab89;
sha1->hashRes[2] = 0x98badcfe;
sha1->hashRes[3] = 0x10325476;
sha1->hashRes[4] = 0xc3d2e1f0;
}
void ProcessEachBlock(sha1_context *sha1)
{
DWORD a, b, c, d, e;//五个缓冲区
DWORD W[80];
DWORD temp;
int i, j;
if(!sha1){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
for (i = 0, j =0; j < 16; i += 4, j++) {//初始化W[0] ~ W[15]
W[j] = (sha1->block[i] << 24) | (sha1->block[i + 1] << 16) |
(sha1->block[i + 2] << 8) | (sha1->block[i + 3]);
//产生一个32位的字
}
for (i = 16; i < 80; i++) {//产生W[16] ~ W[79]
temp = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = RoLeft(temp, 1);
}
//初始化a b c d e
a = sha1->hashRes[0];
b = sha1->hashRes[1];
c = sha1->hashRes[2];
d = sha1->hashRes[3];
e = sha1->hashRes[4];
for ( i = 0; i < 20; i++){//前20
temp = RoLeft(a, 5) + (((c ^ d) & b) ^ d) + e + W[i] + 0x5A827999;//产生新值
//循环赋值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
for (i = 20; i < 40; i++){
temp = RoLeft(a, 5) + (b ^ c ^ d) + e + W[i] + 0x6ED9EBA1;//产生新值
//循环赋值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
for (i = 40; i < 60; i++){
temp = RoLeft(a, 5) + ((b & c) | (b & d) | (c & d)) + e + W[i] + 0x8F1BBCDC;//产生新值
//循环赋值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
for (i = 60; i < 80; i++){
temp = RoLeft(a, 5) + (b ^ c ^ d) + e + W[i] + 0xCA62C1D6;//产生新值
//循环赋值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
//获得新的hash值
sha1->hashRes[0] += a;
sha1->hashRes[1] += b;
sha1->hashRes[2] += c;
sha1->hashRes[3] += d;
sha1->hashRes[4] += e;
}
//每次处理512bit 即是处理64字节
void SHA1Update(sha1_context *sha1,char *data)
{
int i = 0;
if(!sha1 || !data){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
sha1->length += strlen(data);
while (sha1->length >= EACH_HADLE_LEN ){
memcpy(sha1->block, data, EACH_HADLE_LEN);//获得M[i]
ProcessEachBlock(sha1);
data += EACH_HADLE_LEN;//移动到下一个块
sha1->length -= EACH_HADLE_LEN;//减去相应的长度
}
//对最后进行一轮进行一些补位操作 这里先清空 这样就可以不需要填0操作
memset(sha1->block, 0, sizeof(char) * EACH_HADLE_LEN);
memcpy(sha1->block, data, sha1->length);//剩余的数据进行填充
sha1->block[sha1->length] = 0x80;//最高位填充1
unsigned long long bitLen = sha1->length << 3;//获得bit长度 从而填充最后64bit位
memcpy(&(sha1->block[56]), &bitLen, sizeof(unsigned long long));
//直接copy内存的话 因为内存是小端序的所以非常方便 学到了!
for (i = 0; i < 4; i++) {//这里注意要颠倒
DWORD temp = sha1->block[56+i];
sha1->block[56+i] = sha1->block[63 - i];
sha1->block[63 - i] = temp;
}
ProcessEachBlock(sha1);//最后一次运算
}
void PrintSHA1(sha1_context *sha1)
{
int i;
char hashValue[9];
if(!sha1){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
printf("\nresult of the SHA - 1 is : ");
for (i = 0; i < 5; i++) {
memset(hashValue, 0, 9 * sizeof(char));
sprintf(hashValue, "%08x", sha1->hashRes[i]);//得到8个十六进制
printf("%s", hashValue);
}
}
void SHA1Encrypt(char *data)//传入要加密的数据
{
sha1_context sha1 = {0};
SHA1Init(&sha1);//初始化长度
SHA1Update(&sha1, data);//产生40字节的hash值
PrintSHA1(&sha1);
}
int main()
{
char data[] = "message digest";
SHA1Encrypt(data);
}