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

 

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