练习 md5sum

#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;
}


你可能感兴趣的:(练习 md5sum)