MD5哈希算法(C语言实现)
MD5哈希算法(C语言实现)
主要是做个记录,害怕以后代码丢了,先放到这里了。
MD5 暂时就不进行介绍了,最基础的哈希算法,网上到处都是。
转载请注明出处:https://www.cnblogs.com/wangyanzhong123/p/13784318.html
说明
这个版本用了很多位运算,也没有添加注释,所以可能阅读起来会有一些困难。但是可以保证的是结果一定是正确的,并且速度也是经过优化的,应该会很快。
源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#define LEFTSHIFT(x,c) (((x) << (c)) | ((x) >> (32-(c))))
const uint32_t k[64] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
// per-round shift amounts
const uint32_t r[64] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
void to_bytes(uint32_t val, uint8_t *bytes){
bytes[0] = (uint8_t) val;
bytes[1] = (uint8_t) (val >> 8);
bytes[2] = (uint8_t) (val >> 16);
bytes[3] = (uint8_t) (val >> 24);
}
uint32_t to_int32(const uint8_t *bytes){
return (uint32_t)bytes[0]
| ((uint32_t)bytes[1] << 8)
| ((uint32_t)bytes[2] << 16)
| ((uint32_t)bytes[3] << 24);
}
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t* digest){
size_t new_len, offset;
uint32_t words[16];
uint8_t *newmsg = NULL;
uint32_t h0, h1, h2, h3, a, b, c, d, f, g, temp;
h0 = 0x67452301;
h1 = 0xefcdab89;
h2 = 0x98badcfe;
h3 = 0x10325476;
// Pre-processing
// calculate new length (not included last 8bytes)
for (new_len = initial_len+1; new_len % (512/8) != 448/8; new_len++);
newmsg = (uint8_t*)malloc(new_len+8); // 8 bytes for length recording
memcpy(newmsg, initial_msg, initial_len);
newmsg[initial_len]=0x80; // padding "1" first, then all "0"
for (offset = initial_len+1; offset < new_len; offset++)
newmsg[offset] = 0x00;
// append the len in bits at the end of buffer ??? why << 3
to_bytes(initial_len << 3, newmsg + new_len);
to_bytes(initial_len >> 29, newmsg + new_len + 4);
// process the message per 512-bits
for (offset = 0; offset < new_len; offset += (512/8)){
// break 512 bits into 16 words(32-bit)
for (uint32_t i = 0; i < 16; i ++)
words[i] = to_int32(newmsg + offset + i*4);
a = h0; b = h1; c = h2; d = h3;
for (uint32_t i = 0; i < 64; i ++){
if (i < 16) {
f = (b & c) | ((~b) & d);
g = i;
} else if (i < 32) {
f = (d & b) | ((~d) & c);
g = (5*(i-16) + 1) % 16;
} else if (i < 48) {
f = b ^ c ^ d;
g = (3*(i-32) + 5) % 16;
} else {
f = c ^ (b | (~d));
g = (7*(i-48)) % 16;
}
temp = d;
d = c;
c = b;
b = b + LEFTSHIFT((a+f+k[i]+words[g]), r[i]);
a = temp;
}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
}
free(newmsg);
to_bytes(h0, digest);
to_bytes(h1, digest+4);
to_bytes(h2, digest+8);
to_bytes(h3, digest+12);
}
int main(int argc, char **argv){
char *msg;
clock_t start,finish;
double duration;
size_t msglen;
uint8_t result[16];
char *inputstring = "-s";
char *inputfile = "-f";
if (argc < 2){
printf("usage: %s 'string'\n", argv[0]);
return 1;
} else if (!strcmp(argv[1],inputstring)){
msg = argv[2];
msglen = strlen(msg);
start = clock();
md5((uint8_t*)msg, msglen, result);
for (int i = 0; i < 16; i++)
printf("%2.2x", result[i]);
printf("\n");
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf("time cost: %f\n", duration);
system("pause");
return 0;
} else if (!strcmp(argv[1],inputfile)){
FILE *infile;
infile = fopen(argv[2],"rb");
if (infile == NULL){
printf("%s not exist\n",argv[2]);
return -1;
} else {
fseek(infile, 0, SEEK_END);
size_t filesize = ftell(infile);
rewind(infile);
uint8_t *buffer = (uint8_t*)malloc(sizeof(uint8_t)*filesize);
fread(buffer, sizeof(uint8_t), filesize, infile);
start = clock();
md5(buffer, filesize, result);
for (int i = 0; i < 16; i++)
printf("%2.2x", result[i]);
printf("\n");
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf("time cost: %f\n", duration);
system("pause");
return 0;
}
}
}