SHA-1加密算法C语言实现

#include<math.h>
#include<string.h>
#include<malloc.h>
#include<stdio.h>
#include<assert.h>
#define BLOCK_LEN 64
#define MAX_BLOCKS 9
#define MESSAGE_LEN (BLOCK_LEN*(MAX_BLOCKS-1))
#define RESULT_LEN 41
//SHA1算法的上下文,保存一些状态,中间数据,结果
typedef struct sha_1_data {
	char *Ms[MAX_BLOCKS];//保存块指针
	int nblocks;//保存块数
	long long len;//处理的数据的长度
	long long bits;//处理的数据的位数
	int H[5];/* 160-bit algorithm internal hashing state */	
	char *str;//待加密的字符串指针
	char *result;//字符串结果指针
} sha_1_data;
typedef struct Encoder_data {
	char message[MESSAGE_LEN];//待加密的字符串
	char result[RESULT_LEN];//字符串结果指
}Encoder_data;


//循环左移
static inline int S(int x, int s) { //因为存储字符串用的是int类型,所以循环移位要考虑符号的问题
	int temp1 = x << s;
	int temp2 = x >> (32 - s);
	int temp3 = 0;
	for(int i = 0; i<s; i++) {
		temp3 += temp2 & (1<<i);
	}
	return temp1 | temp3;
}

static inline int F1(int x ,int y, int z) {
	return (x & y) | ((~x) & z);
}
static inline int F2(int x, int y, int z) {
	return x ^ y ^ z;
}
static inline int F3(int x, int y, int z) {
	return (x & z) | (y & z)| (x & y);
}
static inline int F4(int x, int y, int z) {
	return x ^ y ^ z;
}
static inline int F(int t,int x, int y, int z) {
	switch(t/20){
		case 0:// 0 <= t< 20
			return F1(x , y, z);
		case 1://20 <= t< 40
			return F2(x , y, z);
		case 2://40 <= t< 60
			return F3(x , y, z);
		case 3://60 <= t< 80
			return F4(x , y, z);
		default:
			assert(false);
	}
}
static inline int K(int t) {	
	switch(t/20){
		case 0:// 0 <= t< 20
			return 0x5A827999;
		case 1://20 <= t< 40
			return 0x6ED9EBA1;
		case 2://40 <= t< 60
			return 0x8F1BBCDC;
		case 3://60 <= t< 80
			return 0xCA62C1D6;
		default:
			assert(false);
	}
}
static inline char * initM() {
	char *M;
	M=(char *)malloc(BLOCK_LEN);
	memset(M,0,BLOCK_LEN);
	return M;
}

static inline sha_1_data * init(sha_1_data *data,Encoder_data *encoder) {
	data->str=encoder->message;
	data->result=encoder->result;
	data->len=strlen(data->str);
	//assert(false);
	if(data->len>511)data->len = MESSAGE_LEN-1; //设定的字符串最大为512,实际511
	data->bits = data->len * 8;
	data->H[0] = 0x67452301;
	data->H[1] = 0xEFCDAB89;
	data->H[2] = 0x98BADCFE;
	data->H[3] = 0x10325476;
	data->H[4] = 0xC3D2E1F0;
	return data;
}
static inline sha_1_data * update(sha_1_data *data) {
	char *M;
	char finish	=0;	//finish flag

	char *tstr=data->str;
	int i,j;
	long long bits=data->bits;
	long long len=data->len;

	M=initM();
	while(!finish) {
		for(j = 0; j < 64&&j < len; j++) M[(j/4)*4+(3-j%4)] = tstr[j];//读入数据 ,M[(j/4)*4+(3-j%4)],以int为单位循环,从高字节到低字节读入单字节
		if(j < 64) {//数据填充
			M[(j/4)*4+(3-j%4)] = 0x80;//数据填充
			if(j >= 56) {//剩下的不足8字节保存长度时
				data->Ms[data->nblocks++]=M;
				M=initM();
			}
			//添加长度,并保存
			*(int *)((M+60))=(int)bits;
			*(int *)((M+56))=(int)(bits>>32);
			data->Ms[data->nblocks++]=M;
			finish=1;//结束标记
		} else {
			if(len>64) { //分组未完成 ,继续读入
				tstr+=64;
			}
			data->Ms[data->nblocks++]=M;//保存快
			M=initM();//分配新的块
			len-=64;//每读512位减64 ,正好为 64时,进入下一循环,也不会处理
		}
	}
	return data;
}
static inline sha_1_data * process(sha_1_data *data) {
	int i,j;
	long long bits=data->bits;
	long long len=data->len;
	int nblocks=data->nblocks;
	char *tstr=data->str;
	int A,B,C,D,E,TEMP;
	int W[80]= {0} ;
	//printf("\n------------------->%d\n",nblocks);
//	for(i = 0; i < nblocks ;i++){
//		for(j = 0; j < 64 ;j++){\
//			printf("%02X",data->Ms[i][j]&0xff);
//			if(j%8==7) printf("\n");
//		}
//	}

	for(i=0; i<nblocks; i++) {
		int *it=(int *)data->Ms[i];
		for(int i=0; i<16; i++) W[i]=it[i];
		for(int i=16; i<80; i++) W[i] = S((W[i-3]^W[i-8]^W[i- 14]^W[i-16]),1);
//
//		for(int j = 0; j < 80;j++){
//			printf("%08X\n",W[j]);
//		}

		A=data->H[0];
		B=data->H[1];
		C=data->H[2];
		D=data->H[3];
		E=data->H[4];

		for(int i=0; i<80; i++) {
			TEMP = S(A,5) + F(i,B,C,D) + E + W[i] + K(i);
			E=D;
			D=C;
			C=S(B,30);
			B=A;
			A=TEMP;
		}

		data->H[0]+=A;
		data->H[1]+=B;
		data->H[2]+=C;
		data->H[3]+=D;
		data->H[4]+=E;
	}
	return data;
}
static inline char * finish(sha_1_data *data) {
	//将数据按字节保存进result字符串中
	for(int i = 0; i < 5 ;i++)sprintf(data->result+8*i,"%08X",data->H[i]);
	for(int i=0; i<data->nblocks; i++) free((void *)(data->Ms[i]));//释放内存
	return data->result;
}
char * SHA_1(Encoder_data *encoder) {
	sha_1_data data= {0};
	//printf("%s",data.str);
	return finish(process(update(init(&data,encoder))));
}
int main() {
	char *s,ret; 
	Encoder_data encoder= {0};
	
//	s=SHA_1(&encoder);
//	printf("message:%s\n",encoder.message);
//	printf("SHA-1:%s\n",s);
	
	static char test_buf[7][81] = {
		{ "" },
		{ "a" },
		{ "abc" },
		{ "message digest" },
		{ "abcdefghijklmnopqrstuvwxyz" },
		{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
		{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
	};
	static const char sha1_test_sum[7][RESULT_LEN] = {
		{ "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" },
		{ "86F7E437FAA5A7FCE15D1DDCB9EAEAEA377667B8" },
		{ "A9993E364706816ABA3E25717850C26C9CD0D89D" },
		{ "C12252CEDA8BE8994D5FA0290A47231C1D16AAE3" },
		{ "32D10C7B8CF96570CA04CE37F2A19D84240D3A89" },
		{ "761C457BF73B14D27E9E9265C46F4B4DDA11F940" },
		{ "50ABF5706A150990A08B2C5EA40FA0E585554732" }
	};
	for(int i=0; i<7; ++i) {
		strcpy(encoder.message,test_buf[i]);
		s=SHA_1(&encoder);
		printf("message:%s\n",encoder.message);
		printf("SHA-1:%s\n",s);
		if ((ret=memcmp(s,sha1_test_sum[i],RESULT_LEN)) != 0) {
			printf("SHA-1:%s\n",sha1_test_sum[i]);
			printf("errornum: %d cmp: %d\n",i,ret);
			assert(false);
		}
	}
}

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值