#include <stdio.h> #include <string.h> #include <stdint.h> /* ref: http://www.ietf.org/rfc/rfc1321.txt http://oss.org.cn/man/develop/rfc/RFC1321.txt http://www.codeforge.cn/read/240035/md5sum.c__html */ static inline void convert_endian_32(uint32_t * in_out) { uint32_t old = *in_out; uint8_t * a = (uint8_t *)in_out; uint8_t * b = (uint8_t *)&old; # define do4(N) a[N] = b[3-N] do4(0); do4(1); do4(2); do4(3); } static inline void convert_endian_64(uint64_t * in_out) { uint64_t old = *in_out; uint8_t * a = (uint8_t *)in_out; uint8_t * b = (uint8_t *)&old; # define do8(N) a[N] = b[7-N] do8(0); do8(1); do8(2); do8(3); do8(4); do8(5); do8(6); do8(7); } static inline void convert_endian_32_array(uint32_t in_out[], uint32_t num) { uint32_t i; for(i = 0; i < num; i++) { convert_endian_32(in_out + i); } } static int judge_endian(void) { union { uint32_t i; uint8_t c; } u; u.i = 1; return u.c == 0; // return 1 if big endian } #define FF(b,c,d) ( d ^ (b & (c ^ d)) ) // ( (b & c) | (~b & d) ) #define FG(b,c,d) FF(d, b, c) // ( (b & d) | (c & ~d) ) #define FH(b,c,d) ( b ^ c ^ d ) #define FI(b,c,d) ( c ^ (b | ~d) ) #define ROLL(a,s) ( (a<<s) | (a>>(32-s)) ) #define OP(func, a,b,c,d, k,s,t) a+=func(b,c,d)+in[k]+t; a=b+ROLL(a,s) static void md5_transform(uint32_t abcd[4], const uint32_t in[16]) { uint32_t A = abcd[0]; uint32_t B = abcd[1]; uint32_t C = abcd[2]; uint32_t D = abcd[3]; OP(FF, A, B, C, D, 0, 7, 0xd76aa478); OP(FF, D, A, B, C, 1, 12, 0xe8c7b756); OP(FF, C, D, A, B, 2, 17, 0x242070db); OP(FF, B, C, D, A, 3, 22, 0xc1bdceee); OP(FF, A, B, C, D, 4, 7, 0xf57c0faf); OP(FF, D, A, B, C, 5, 12, 0x4787c62a); OP(FF, C, D, A, B, 6, 17, 0xa8304613); OP(FF, B, C, D, A, 7, 22, 0xfd469501); OP(FF, A, B, C, D, 8, 7, 0x698098d8); OP(FF, D, A, B, C, 9, 12, 0x8b44f7af); OP(FF, C, D, A, B, 10, 17, 0xffff5bb1); OP(FF, B, C, D, A, 11, 22, 0x895cd7be); OP(FF, A, B, C, D, 12, 7, 0x6b901122); OP(FF, D, A, B, C, 13, 12, 0xfd987193); OP(FF, C, D, A, B, 14, 17, 0xa679438e); OP(FF, B, C, D, A, 15, 22, 0x49b40821); OP(FG, A, B, C, D, 1, 5, 0xf61e2562); OP(FG, D, A, B, C, 6, 9, 0xc040b340); OP(FG, C, D, A, B, 11, 14, 0x265e5a51); OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP(FG, A, B, C, D, 5, 5, 0xd62f105d); OP(FG, D, A, B, C, 10, 9, 0x02441453); OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); OP(FG, D, A, B, C, 14, 9, 0xc33707d6); OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); OP(FG, B, C, D, A, 8, 20, 0x455a14ed); OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP(FG, C, D, A, B, 7, 14, 0x676f02d9); OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); OP(FH, A, B, C, D, 5, 4, 0xfffa3942); OP(FH, D, A, B, C, 8, 11, 0x8771f681); OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); OP(FH, B, C, D, A, 14, 23, 0xfde5380c); OP(FH, A, B, C, D, 1, 4, 0xa4beea44); OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); OP(FH, B, C, D, A, 6, 23, 0x04881d05); OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); OP(FI, A, B, C, D, 0, 6, 0xf4292244); OP(FI, D, A, B, C, 7, 10, 0x432aff97); OP(FI, C, D, A, B, 14, 15, 0xab9423a7); OP(FI, B, C, D, A, 5, 21, 0xfc93a039); OP(FI, A, B, C, D, 12, 6, 0x655b59c3); OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP(FI, C, D, A, B, 10, 15, 0xffeff47d); OP(FI, B, C, D, A, 1, 21, 0x85845dd1); OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP(FI, C, D, A, B, 6, 15, 0xa3014314); OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); OP(FI, A, B, C, D, 4, 6, 0xf7537e82); OP(FI, D, A, B, C, 11, 10, 0xbd3af235); OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP(FI, B, C, D, A, 9, 21, 0xeb86d391); abcd[0] += A; abcd[1] += B; abcd[2] += C; abcd[3] += D; } int main(int argc, char * argv[]) { if(argc != 2) { return 1; } FILE * f = fopen(argv[1], "rb"); if(!f) { return 2; } int is_big_endian = judge_endian(); uint32_t abcd[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; uint64_t bit_sum = 0; for(;;) { uint32_t in[32]; //128 bytes size_t n = fread(in, 1, 64, f); bit_sum += n * 8; if(n == 64) { if(is_big_endian) { convert_endian_32_array(in, 16); } md5_transform(abcd, in); } else { uint8_t * buf = (uint8_t *)in; memset(buf + n, 0, 128 - n); buf[n] = 0x80; uint64_t * p_len = (uint64_t *)(n < 56 ? &buf[64-8] : &buf[128-8]); *p_len = bit_sum; if(is_big_endian) { convert_endian_64(p_len); convert_endian_32_array(in, 32); } md5_transform(abcd, in); if(n >= 56) { md5_transform(abcd, in + 16); } break; } } fclose(f); int i; for(i = 0; i < 4; i++) { convert_endian_32(abcd + i); printf("%08x", abcd[i]); } printf("\n"); return 0; }