#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);
}
}
}
SHA-1加密算法C语言实现
最新推荐文章于 2024-05-13 19:00:47 发布