#include <stdio.h>
#include <stdlib.h>
#define A (0x67452301)
#define B (0xefcdab89)
#define C (0x98badcfe)
#define D (0x10325476)
#define X(_a, _b, _r, _m, _s, _t) \
((_a) = (_b) + rol((_a) + (_r) + (_m) + (_t), (_s)))
const int N[4][2] = {{0, 1}, {1, 5}, {5, 3}, {0, 7}};
const unsigned long S[4][4] = {
{7, 12, 17, 22},
{5, 9, 14, 20},
{4, 11, 16, 23},
{6, 10, 15, 21}
};
//(4294967296 * abs(sin(i *16 + j + 1)))
const unsigned long T[4][16] = {
{
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
}
};
//DESP: MD5 F
unsigned long F(unsigned long x, unsigned long y, unsigned long z)
{
return (x & y) | ((~x) & z);
}
//DESP: MD5 G
unsigned long G(unsigned long x, unsigned long y, unsigned long z)
{
return (x & z) | (y & (~z));
}
//DESP: MD5 H
unsigned long H(unsigned long x, unsigned long y, unsigned long z)
{
return (x ^ y ^ z);
}
//DESP: MD5 I
unsigned long I(unsigned long x, unsigned long y, unsigned long z)
{
return y ^ (x | (~z));
}
//non-line function
unsigned long ((*md5nl[4])(unsigned long x, unsigned long y, unsigned long z)) = {
F, G, H, I
};
//DESP: Rotate Left
unsigned long rol(unsigned long n, unsigned long c)
{
return (n << c) | (n >> (32 - c));
}
//DESP: MD5 update
void md5_update(unsigned long chain[4], unsigned long msg[16])
{
unsigned long state[4];
int i, j, n, k;
//DO: copy state
for(i = 0; i < 4; i++)
state[i] = chain[i];
for(i = 0; i < 4; i++) {
n = N[i][0];
for(j = 0; j < 16; j++) {
k = ((4 - (j & 3)) & 3);
//DO: md5 FF,GG,HH,II
X(state[k],
state[(k + 1) & 3],
md5nl[i](state[(k + 1) & 3], state[(k + 2) & 3], state[(k + 3) & 3]),
msg[n & 0x0f],
S[i][j & 3],
T[i][j]);
n += N[i][1];
}
}
//DO: add to chain
for(i = 0; i < 4; i++)
chain[i] += state[i];
return;
}
//DESP: MD5 final
void md5_final(unsigned long chain[4], unsigned char *tail, unsigned long len[2])
{
unsigned char msg[128];
int i, l, n;
//tail length
l = len[0] & 0x3f;
//buffer size
n = (l >= 56)? 120: 56;
//copy tail to buffer
for(i = 0; i < l; i++)
msg[i] = tail[i];
if(n > l) {
//DO: fill message
msg[l] = 0x80;
for(i = l + 1; i < n; i++)
msg[i] = 0;
}
//append bits length to message
((unsigned long *)(msg + n))[0] = len[0] << 3;
((unsigned long *)(msg + n))[1] = len[1] << 3 | len[0] >> 29;
md5_update(chain, (unsigned long *)msg);
if(n == 120)
md5_update(chain, (unsigned long *)&msg[64]);
return;
}
//DESP: MD5 initialize chaining variables
void md5_init(unsigned long chain[4])
{
chain[0] = A;
chain[1] = B;
chain[2] = C;
chain[3] = D;
return;
}
#define BLOCK_SIZE (0x1000 * sizeof(unsigned char))
#define BLOCK_DWORD (BLOCK_SIZE / sizeof(unsigned long))
#define MSG_SIZE (0x40 * sizeof(unsigned char))
#define MSG_DWORD (MSG_SIZE / sizeof(unsigned long))
//DESP: update chain for echo 4kb
void md5_file_block(unsigned long sum[4], unsigned long block[BLOCK_DWORD])
{
int i;
for(i = 0; i < BLOCK_DWORD; i += MSG_DWORD)
md5_update(sum, &block[i]);
return;
}
//DESP: final chain
void md5_file_final(unsigned long sum[4], unsigned long *block, unsigned long len[2])
{
int i, n;
//count of block
n = (len[0] % BLOCK_SIZE) / MSG_SIZE;
//reserve
if((len[0] % MSG_SIZE) == 0)
n--;
n *= MSG_DWORD;
for(i = 0; i < n; i += MSG_DWORD)
md5_update(sum, &block[i]);
md5_final(sum, (unsigned char *)&block[i], len);
return;
}
//DESP: demo for compute file's MD5
int md5_file(char *file, unsigned char result[16])
{
FILE *in;
int r;
unsigned long n;
unsigned long *p;
unsigned long l[2];
unsigned long sum[4];
//open file
if(fopen_s(&in, file, "rb") != 0)
return 0;
l[0] = l[1] = 0;
p = (unsigned long *)malloc(BLOCK_SIZE);
if(!p) {
fclose(in);
return 0;
}
r = 1;
md5_init(sum);
for(;;) {
n = fread(p, sizeof(unsigned char), BLOCK_SIZE, in);
if(ferror(in)) {
r = 0;
break;
}
if(feof(in)) {
n += l[0];
if(n < l[0])
l[1]++;
md5_final(sum, (unsigned char *)p, l);
for(n = 0; n < 4; n++)
((unsigned long *)result)[n] = sum[n];
break;
} else {
md5_file_block(sum, p);
n += l[0];
if(n < l[0])
l[1]++;
}
}
free(p);
fclose(in);
return r;
}
int main(int argc, char *argv[])
{
int i;
unsigned char sum[16];
if(argc == 2) {
if(!md5_file(argv[1], sum))
return 1;
for(i = 0; i < 16; i++)
printf("%02x", sum[i]);
putchar(' ');
puts(argv[1]);
return 0;
}
return 1;
}
计算文件MD5(含MD5算法)
最新推荐文章于 2023-05-17 13:43:27 发布