2011-08-20 21:01:39Morris

MD5 實作

輸入的字串, 用8bits, 改變成二進制, 之後補一個1, 直到bit length %512 = 448
剩餘的64 bits 給原始的字串長度(bit length)

"aakljhsdfglihjaewlkasldfkj aldkjgaid a iuehn cxzhjbqwe lknKJDNF  UHEWK RJNAKS KHWEIURHKAJSNDBVAJksjdhfa adfkjh"

01100001  97 01100001  97 01101011 107 01101100 108 01101010 106 01101000 104
01110011 115 01100100 100 01100110 102 01100111 103 01101100 108 01101001 105
01101000 104 01101010 106 01100001  97 01100101 101 01110111 119 01101100 108
01101011 107 01100001  97 01110011 115 01101100 108 01100100 100 01100110 102
01101011 107 01101010 106 00100000  32 01100001  97 01101100 108 01100100 100
01101011 107 01101010 106 01100111 103 01100001  97 01101001 105 01100100 100
00100000  32 01100001  97 00100000  32 01101001 105 01110101 117 01100101 101
01101000 104 01101110 110 00100000  32 01100011  99 01111000 120 01111010 122
01101000 104 01101010 106 01100010  98 01110001 113 01110111 119 01100101 101
00100000  32 01101100 108 01101011 107 01101110 110 01001011  75 01001010  74
01000100  68 01001110  78 01000110  70 00100000  32 00100000  32 01010101  85
01001000  72 01000101  69 01010111  87 01001011  75 00100000  32 01010010  82
01001010  74 01001110  78 01000001  65 01001011  75 01010011  83 00100000  32
01001011  75 01001000  72 01010111  87 01000101  69 01001001  73 01010101  85
01010010  82 01001000  72 01001011  75 01000001  65 01001010  74 01010011  83
01001110  78 01000100  68 01000010  66 01010110  86 01000001  65 01001010  74
01101011 107 01110011 115 01101010 106 01100100 100 01101000 104 01100110 102
01100001  97 00100000  32 01100001  97 01100100 100 01100110 102 01101011 107
01101010 106 01101000 104 10000000 128 00000000   0 00000000   0 00000000   0
00000000   0 00000000   0 00000000   0 00000000   0 00000000   0 00000000   0
01110000 112 00000011   3 00000000   0 00000000   0 00000000   0 00000000   0
00000000   0 00000000   0

紅色是原始, 藍色是補 1, 綠色是原始長度

範例輸入 :

a

abc
message digest
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
abcdefg

範例輸出 :
D41D8CD98F00B204E9800998ECF8427E
0CC175B9C0F1B6A831C399E269772661
DAA1A373AFB44D2540D6452013C23C82
F96B697D7CB7938D525A2F31AAF161D0
C3FCD3D76192E4007DFB496CCA67E13B
F29939A25EFABAEF3B87E2CBFE641315
3718A5F5B3212D3D1C782436FADB1C3A
E7C4509687A708D1FF1F409212D903FB

以下程式碼, 參考百度的寫法, 多了一些自己的做法, 不過還是靜態的

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef unsigned long UINT32;
typedef unsigned long long UINT64;
UINT32 F(UINT32 x, UINT32 y, UINT32 z) {
    return (x & y) | (~x & z);
}
UINT32 G(UINT32 x, UINT32 y, UINT32 z) {
    return (x & z) | (y & ~z);
}
UINT32 H(UINT32 x, UINT32 y, UINT32 z) {
    return x ^ y ^ z;
}
UINT32 I(UINT32 x, UINT32 y, UINT32 z) {
    return y ^ (x | ~z);
}
UINT32 rotate_left(UINT32 x, UINT32 n) {
    return  (x << n) | (x >> (32-n));
}
void MD5(char in[]) {
    UINT32 S[4][4] = {{7, 12, 17, 22}, {5, 9, 14, 20}, {4, 11, 16, 23}, {6, 10, 15, 21}};
    UINT32 X[16], T[65], chain[4] ={0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
    UINT32 Xinit[4][2] = {{0, 1}, {1, 5}, {5, 3}, {0, 7}};
    int i, j, roundIdx, xIdx, sIdx;
    UINT32 ( *Function[4])(UINT32, UINT32, UINT32) = {F, G, H, I};
    for(i = 1; i <= 64; i++)    T[i] = (UINT32)floor((1ULL << 32)*fabs(sin(i)));
    UINT32 length = strlen(in)+1, bit_length = 8*length, tlength = (length-1)*8;
    UINT32 Copy[length+513], supply, state[4];
    for(i = 0; i < length; i++)    Copy[i] = in[i] < 0 ? (128-abs(in[i]))+(1<<7) : in[i];
    Copy[length-1] = 1 << 7;
    supply = bit_length % 512;
    supply = (supply > 448) ? (512-supply+448) : (448-supply);
    for(i = supply/8; i >= 0; i--, length++)    Copy[length] = 0;
    for(i = length-1; tlength; i++)
        Copy[i] = tlength % 256, tlength /= 256;
    bit_length = (length-1)*8+64, length = bit_length/8;
    for(i = 0; i < length; i += 64) {
        state[0] = chain[0], state[1] = chain[1];
        state[2] = chain[2], state[3] = chain[3];
        for(j = 0; j < 16; j++)
            X[j] = (Copy[i+j*4+3]<<24) | (Copy[i+j*4+2]<<16) | (Copy[i+j*4+1]<<8) | Copy[i+j*4];
        for(roundIdx = 0; roundIdx < 4; roundIdx++) {
            xIdx = Xinit[roundIdx][0], sIdx = 0;
            for(j = 0; j < 16; j++) {
                state[sIdx] = state[(sIdx+1)%4] + rotate_left(
                    state[sIdx] + ( *Function[roundIdx])(state[(sIdx+1)%4], state[(sIdx+2)%4], state[(sIdx+3)%4])
                    + X[xIdx] + T[roundIdx*16+j+1], S[roundIdx][j%4]
                );
                sIdx = (sIdx + 3) % 4;
                xIdx = (xIdx + Xinit[roundIdx][1]) & 0xF;
            }
        }
        chain[0] += state[0], chain[1] += state[1];
        chain[2] += state[2], chain[3] += state[3];
    }
    char r[33];
    for(i = 0; i < 4; i++)
        for(j = 0; j < 8; j += 2)
            sprintf(r+i*8+j, "%02X", chain[i] & 0xff), chain[i] >>= 8;
    r[32] = '\0';
    puts(r);
}
main() {
    char S[20000];
    while(gets(S))            
        MD5(S);
    return 0;
}
(悄悄話) 2011-12-04 01:46:53