此文章是vip文章,如何查看?  

1,点击链接获取密钥 http://nicethemes.cn/product/view29882.html

2,在下方输入文章查看密钥即可立即查看当前vip文章


SHA1加密(c实现)

  • 时间:
  • 浏览:
  • 来源:互联网

在vs2013下编译且成功实现。

SHA1加密算法实现思路:
前提:需要一个
unsigned long W[80]
unsigned long H[5]
unsigned long a,b,c,d,e
unsigned long temp

对明文首先进行填充,假设明文为p,
则p的bit长度要满足 % 512 == 448
不满足需要高位填充一个1,其余位补充0,最后的64位填充长度,假设bit长度为0x70 注意内存里 我们看到的是00 00 00 00 00 00 00 70(十六进制)

填充完后 512bit(64字节)一组 每组分成32个字(4字节)
首先需要将W[0] ~ W[15]填充为我们自己的data
然后依据

temp = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = RoLeft(temp, 1);

生成之后的W[i],其中RoLeft为循环左移n位

接着就可以进行运算了,首先H[5]数组的五个常数起始值,然后传递给a,b,c,d,e作为临时变量存储中间结果,最后再赋值给H[5]作为下一个块的起始值。
运算过程:每20组会更换一个常数Ki和一个迭代公式
具体参考代码如下(c实现):

/*
SHA1 算法产出的是160位的摘要 即 32 * 5长度
有五个字(这里为32位)
*/

#include <cstdio>
#include <cstring>
#include <Windows.h>
#pragma warning(disable:4309)
#pragma warning(disable:4996)
#define EACH_HADLE_LEN 64//每次处理64字节

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

	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)
{
	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 (int 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];

	printf("\nresult of the SHA - 1 is : ");

	for (i = 0; i < 5; i++) {
		ZeroMemory(hashValue, 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";
	printf("len of plainText : %x\n", strlen(data) << 3);
	SHA1Encrypt(data);
}

本文链接http://element-ui.cn/news/show-576950.aspx