SHA1算法代码实现

sha1释义:安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准 (Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 

sha1特点:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要,所以可以用摘要来校验信息是否正确

代码如下所示:

/*
    SHA1 算法产出的是160位的摘要 即 32 * 5长度
    有五个字(这里为32位)
*/
#include <stdio.h>
#include <string.h>

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章