사용자 도구

사이트 도구


kb:md5hashing

MD5 Hashing

MD5는 해쉬 알고리즘의 일종이다. 즉 문자열이나 파일 같은 것을 읽어들여서 이를 일정한 값으로 요악하는 알고리즘이다. 암호화와 관련해서 원문 확인용으로 쓰일 때가 있다. Win32에서도 사용가능한 함수가 있기는 하지만, Base64Encoding과 관련해서 인터넷을 뒤지다가 있길래 같이 만들어버렸다.

C++ Implementation

MD5.h
//////////////////////////////////////////////////////////////////////////////
// Filename    : MD5.h
// Written By  : excel96
// Created     : 2003.3.6
// Description : 
//////////////////////////////////////////////////////////////////////////////
 
#ifndef __MD5_H__
#define __MD5_H__
 
#ifndef __MTYPES_H__
    #include "MTypes.h"
#endif
 
#ifndef _INC_STDIO
    #include <stdio.h>
#endif
 
#ifndef _FSTREAM_
    #include <fstream>
#endif
 
#ifndef _IOSTREAM_
    #include <iostream>
#endif
 
//////////////////////////////////////////////////////////////////////////////
// Classname   : MD5
// Description : 
//////////////////////////////////////////////////////////////////////////////
// TEST SUITE
// MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
// MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
// MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
// MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
// MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
// MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
// d174ab98d277d9f5a5611c2c9f419d9f
// MD5 ("123456789012345678901234567890123456789012345678901234567890123456
// 78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
//////////////////////////////////////////////////////////////////////////////
 
class MD5 
{
private:
    static BYTE PADDING[64];
 
    DWORD m_pState[4];
    DWORD m_pCount[2];   // number of* bits*, mod 2^64
    BYTE  m_pBuffer[64]; // input buffer
    BYTE  m_pDigest[16];
    BYTE  m_bFinalized;
 
 
public:
    MD5();                      // simple initializer
    MD5(BYTE* pString);         // digest string, finalize
    MD5(istream& stream);       // digest stream, finalize
    MD5(FILE* file);            // digest file, close, finalize
    MD5(ifstream& stream);      // digest stream, close, finalize
 
 
public:
    void update(BYTE* input, DWORD input_length);
    void update(istream& stream);
    void update(FILE* file);
    void update(ifstream& stream);
    void finalize();
 
 
public:
    // digest as a 16-byte binary array
    // don't forget to delete returned array
    BYTE* digest2binary(); 
 
    // digest as a 33-byte ascii-hex string
    string digest2hexstring(); 
 
    // test function
    static bool testMe();
 
 
private:
    // called by all constructors
    void init();               
 
    // does the real update work. Note that length is implied to be 64.
    void transform(BYTE* buffer);  
 
    static void encode(BYTE* dest, DWORD* src, DWORD length);
    static void decode(DWORD* dest, BYTE* src, DWORD length);
    static void memcpy(BYTE* dest, BYTE* src, DWORD length);
    static void memset(BYTE* start, BYTE val, DWORD length);
 
    static inline DWORD rotate_left(DWORD x, DWORD n);
    static inline DWORD F(DWORD x, DWORD y, DWORD z);
    static inline DWORD G(DWORD x, DWORD y, DWORD z);
    static inline DWORD H(DWORD x, DWORD y, DWORD z);
    static inline DWORD I(DWORD x, DWORD y, DWORD z);
 
    static inline void FF(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac);
    static inline void GG(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac);
    static inline void HH(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac);
    static inline void II(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac);
};
 
#endif //__MD5_H__
MD5.cpp
//////////////////////////////////////////////////////////////////////////////
// Filename    : MD5.cpp
// Written By  : excel96
// Created     : 2003.3.6
// Description : 
//////////////////////////////////////////////////////////////////////////////
 
#include "MD5.h"
#include <iostream>
 
// Constants for MD5Transform routine.
// Although we could use C++ style constants, defines are actually better,
// since they let us easily evade scope clashes.
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
 
BYTE MD5::PADDING[64] =
{
    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::MD5
// Return type     : 
// Description     : 
// MD5 simple initialization method
//////////////////////////////////////////////////////////////////////////////
MD5::MD5()
{
    init();
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::MD5
// Return type     : 
// Argument        : BYTE* pString
// Description     : 
//////////////////////////////////////////////////////////////////////////////
MD5::MD5(BYTE* pString)
{
    init(); // must be called be all constructors
    update(pString, strlen((const char*)pString));
    finalize();
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::MD5
// Return type     : 
// Argument        : FILE *file
// Description     : 
//////////////////////////////////////////////////////////////////////////////
MD5::MD5(FILE *file)
{
    init(); // must be called be all constructors
    update(file);
    finalize();
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::MD5
// Return type     : 
// Argument        : istream& stream
// Description     : 
//////////////////////////////////////////////////////////////////////////////
MD5::MD5(istream& stream)
{
    init(); // must called by all constructors
    update(stream);
    finalize();
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::MD5
// Return type     : 
// Argument        : ifstream& stream
// Description     : 
//////////////////////////////////////////////////////////////////////////////
MD5::MD5(ifstream& stream)
{
    init();  // must called by all constructors
    update(stream);
    finalize();
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : 
// Return type     : void MD5::update 
// Argument        : BYTE *input
// Argument        : DWORD input_length
// Description     : 
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
//////////////////////////////////////////////////////////////////////////////
void MD5::update(BYTE* input, DWORD input_length) 
{
    DWORD input_index, buffer_index;
    DWORD buffer_space; // how much space is left in buffer
 
    if (m_bFinalized)
    {  
        // so we can't update!
        cerr << "MD5::update: Can't update a finalized digest!" << endl;
        return;
    }
 
    // Compute number of bytes mod 64
    buffer_index = (DWORD)((m_pCount[0] >> 3) & 0x3F);
 
    // Update number of bits
    if ((m_pCount[0] += ((DWORD) input_length << 3))<((DWORD) input_length << 3))
        m_pCount[1]++;
 
    m_pCount[1] += ((DWORD)input_length >> 29);
 
    buffer_space = 64 - buffer_index;  // how much space is left in buffer
 
    // Transform as many times as possible.
    if (input_length >= buffer_space) 
    { 
        // ie. we have enough to fill the buffer
        // fill the rest of the buffer and transform
        MD5::memcpy(m_pBuffer + buffer_index, input, buffer_space);
        transform(m_pBuffer);
 
        // now, transform each 64-byte piece of the input, bypassing the buffer
        for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64)
            transform(input+input_index);
 
        buffer_index = 0;  // so we can buffer remaining
    }
    else
    {
        input_index=0;     // so we can buffer the whole input
    }
 
    // and here we do the buffering:
    MD5::memcpy(m_pBuffer+buffer_index, input+input_index, input_length-input_index);
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::update
// Return type     : void 
// Argument        : FILE *file
// Description     : 
// MD5 update for files.
// Like above, except that it works on files(and uses above as a primitive.)
//////////////////////////////////////////////////////////////////////////////
void MD5::update(FILE *file)
{
    BYTE buffer[1024];
    int len;
 
    while (len = fread(buffer, 1, 1024, file))
        update(buffer, len);
 
    fclose(file);
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::update
// Return type     : void 
// Argument        : istream& stream
// Description     : 
// MD5 update for istreams.
// Like update for files; see above.
//////////////////////////////////////////////////////////////////////////////
void MD5::update(istream& stream)
{
    BYTE buffer[1024];
    int len;
 
    while (stream.good())
    {
        // note that return value of read is unusable.
        stream.read((char*)&buffer[0], 1024); 
        len = stream.gcount();
        update(buffer, len);
    }
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::update
// Return type     : void 
// Argument        : ifstream& stream
// Description     : 
// MD5 update for ifstreams.
// Like update for files; see above.
//////////////////////////////////////////////////////////////////////////////
void MD5::update(ifstream& stream)
{
    BYTE buffer[1024];
    int len;
 
    while (stream.good())
    {
        // note that return value of read is unusable.
        stream.read((char*)&buffer[0], 1024); 
        len = stream.gcount();
        update(buffer, len);
    }
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::finalize
// Return type     : void 
// Description     : 
// MD5 finalization. Ends an MD5 message-digest operation, 
// writing the the message digest and zeroizing the context.
//////////////////////////////////////////////////////////////////////////////
void MD5::finalize()
{
    BYTE bits[8];
    DWORD index, padLen;
 
    if (m_bFinalized)
    {
        cerr << "MD5::finalize:  Already finalized this digest!" << endl;
        return;
    }
 
    // Save number of bits
    encode(bits, m_pCount, 8);
 
    // Pad out to 56 mod 64.
    index = (DWORD)((m_pCount[0] >> 3) & 0x3f);
    padLen = (index < 56) ?(56 - index) :(120 - index);
    update(MD5::PADDING, padLen);
 
    // Append length(before padding)
    update(bits, 8);
 
    // Store state in digest
    encode(m_pDigest, m_pState, 16);
 
    // Zeroize sensitive information
    MD5::memset(m_pBuffer, 0, sizeof(*m_pBuffer));
 
    m_bFinalized = true;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::digest2binary
// Return type     : BYTE* 
// Description     : 
//////////////////////////////////////////////////////////////////////////////
BYTE* MD5::digest2binary()
{
    BYTE *s = new BYTE[16];
 
    if (!m_bFinalized)
    {
        cerr << "MD5::digest2binary: "
            << "Can't get digest if you haven't finalized the digest!" 
            << endl;
 
        return ((BYTE*)"");
    }
 
    MD5::memcpy(s, m_pDigest, 16);
 
    return s;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::digest2hexstring
// Return type     : string
// Description     : 
//////////////////////////////////////////////////////////////////////////////
string MD5::digest2hexstring()
{
    if (!m_bFinalized)
    {
        cerr << "MD5::digest2hexstring: "
            << "Can't get digest if you haven't finalized the digest!" 
            << endl;
 
        return "";
    }
 
    char s[34] = {0, };
 
    for (int i=0; i < 16; i++)
    {
        sprintf(s + i*2, "%02x", m_pDigest[i]);
    }
 
    s[32] = '\0';
 
    return string(s);
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::testMe
// Return type     : bool
// Description     : 
// test function
//////////////////////////////////////////////////////////////////////////////
bool MD5::testMe()
{
    char* input[7] = 
    {
        "",
        "a",
        "abc",
        "message digest",
        "abcdefghijklmnopqrstuvwxyz",
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
        "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
    };
 
    string expected[7] = 
    {
        "d41d8cd98f00b204e9800998ecf8427e",
        "0cc175b9c0f1b6a831c399e269772661",
        "900150983cd24fb0d6963f7d28e17f72",
        "f96b697d7cb7938d525a2f31aaf161d0",
        "c3fcd3d76192e4007dfb496cca67e13b",
        "d174ab98d277d9f5a5611c2c9f419d9f",
        "57edf4a22be3c955ac49da2e2107b67a"
    };
 
    MD5 test1((BYTE*)input[0]);
    MD5 test2((BYTE*)input[1]);
    MD5 test3((BYTE*)input[2]);
    MD5 test4((BYTE*)input[3]);
    MD5 test5((BYTE*)input[4]);
    MD5 test6((BYTE*)input[5]);
    MD5 test7((BYTE*)input[6]);
 
    if (test1.digest2hexstring() != expected[0]) return false;
    if (test2.digest2hexstring() != expected[1]) return false;
    if (test3.digest2hexstring() != expected[2]) return false;
    if (test4.digest2hexstring() != expected[3]) return false;
    if (test5.digest2hexstring() != expected[4]) return false;
    if (test6.digest2hexstring() != expected[5]) return false;
    if (test7.digest2hexstring() != expected[6]) return false;
 
    return true;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::init
// Return type     : void 
// Description     : 
//////////////////////////////////////////////////////////////////////////////
void MD5::init()
{
    m_bFinalized = false;  // we just started!
 
    // Nothing counted, so count=0
    m_pCount[0] = 0;
    m_pCount[1] = 0;
 
    // Load magic initialization constants.
    m_pState[0] = 0x67452301;
    m_pState[1] = 0xefcdab89;
    m_pState[2] = 0x98badcfe;
    m_pState[3] = 0x10325476;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::transform
// Return type     : void 
// Argument        : BYTE block[64]
// Description     : 
// MD5 basic transformation. Transforms state based on block.
//////////////////////////////////////////////////////////////////////////////
void MD5::transform(BYTE block[64])
{
    DWORD a = m_pState[0];
    DWORD b = m_pState[1];
    DWORD c = m_pState[2];
    DWORD d = m_pState[3];
    DWORD x[16];
 
    decode(x, block, 64);
 
    // not just a user error, since the method is private
    Assert(!m_bFinalized); 
 
    /* Round 1 */
    FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
    FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
    FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
    FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
    FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
    FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
    FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
    FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
    FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
    FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
 
    /* Round 2 */
    GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
    GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
    GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
    GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
    GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
    GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
    GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
    GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
    GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
    GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
    GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
 
    /* Round 3 */
    HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
    HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
    HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
    HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
    HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
    HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
    HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
    HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
    HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
    HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
 
    /* Round 4 */
    II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
    II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
    II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
    II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
    II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
    II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
    II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
    II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
    II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
    II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
 
    m_pState[0] += a;
    m_pState[1] += b;
    m_pState[2] += c;
    m_pState[3] += d;
 
    // Zeroize sensitive information.
    MD5::memset((BYTE *) x, 0, sizeof(x));
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::encode
// Return type     : void 
// Argument        : BYTE *output
// Argument        : DWORD *input
// Argument        : DWORD len
// Description     : 
// Encodes input(UINT4) into output(BYTE). 
// Assumes len is a multiple of 4.
//////////////////////////////////////////////////////////////////////////////
void MD5::encode(BYTE *output, DWORD *input, DWORD len) 
{
    DWORD i, j;
    for (i = 0, j = 0; j < len; i++, j += 4) 
    {
        output[j]   = (BYTE) (input[i] & 0xff);
        output[j+1] = (BYTE)((input[i] >> 8) & 0xff);
        output[j+2] = (BYTE)((input[i] >> 16) & 0xff);
        output[j+3] = (BYTE)((input[i] >> 24) & 0xff);
    }
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::decode
// Return type     : void 
// Argument        : DWORD* output
// Argument        : BYTE* input
// Argument        : DWORD len
// Description     : 
// Decodes input(BYTE) into output(UINT4). 
// Assumes len is a multiple of 4.
//////////////////////////////////////////////////////////////////////////////
void MD5::decode(DWORD* output, BYTE* input, DWORD len)
{
    DWORD i, j;
 
    for (i = 0, j = 0; j < len; i++, j += 4)
    {
        output[i] = ((DWORD)input[j]) | (((DWORD)input[j+1]) << 8) |
            (((DWORD)input[j+2]) << 16) |(((DWORD)input[j+3]) << 24);
    }
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::memcpy
// Return type     : void 
// Argument        : BYTE* output
// Argument        : BYTE* input
// Argument        : DWORD len
// Description     : 
// Note: Replace "for loop" with standard memcpy if possible.
//////////////////////////////////////////////////////////////////////////////
void MD5::memcpy(BYTE* output, BYTE* input, DWORD len)
{
    for (DWORD i = 0; i < len; i++)
        output[i] = input[i];
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::memset
// Return type     : void 
// Argument        : BYTE* output
// Argument        : BYTE value
// Argument        : DWORD len
// Description     : 
// Note: Replace "for loop" with standard memset if possible.
//////////////////////////////////////////////////////////////////////////////
void MD5::memset(BYTE* output, BYTE value, DWORD len)
{
    for (DWORD i = 0; i < len; i++)
        output[i] = value;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : int MD5::rotate_left 
// Return type     : unsigned 
// Argument        : DWORD x
// Argument        : DWORD n
// Description     : 
// ROTATE_LEFT rotates x left n bits.
//////////////////////////////////////////////////////////////////////////////
inline DWORD MD5::rotate_left(DWORD x, DWORD n)
{
    return(x << n) |(x >>(32-n))  ;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::F
// Return type     : DWORD 
// Argument        : DWORD x
// Argument        : DWORD y
// Argument        : DWORD z
// Description     : 
// F, G, H and I are basic MD5 functions.
//////////////////////////////////////////////////////////////////////////////
inline DWORD MD5::F(DWORD x, DWORD y, DWORD z)
{
    return(x & y) |(~x & z);
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::G
// Return type     : DWORD 
// Argument        : DWORD x
// Argument        : DWORD y
// Argument        : DWORD z
// Description     : 
// F, G, H and I are basic MD5 functions.
//////////////////////////////////////////////////////////////////////////////
inline DWORD MD5::G(DWORD x, DWORD y, DWORD z)
{
    return(x & z) |(y & ~z);
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::H
// Return type     : DWORD 
// Argument        : DWORD x
// Argument        : DWORD y
// Argument        : DWORD z
// Description     : 
// F, G, H and I are basic MD5 functions.
//////////////////////////////////////////////////////////////////////////////
inline DWORD MD5::H(DWORD x, DWORD y, DWORD z)
{
    return x ^ y ^ z;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::I
// Return type     : DWORD 
// Argument        : DWORD x
// Argument        : DWORD y
// Argument        : DWORD z
// Description     : 
// F, G, H and I are basic MD5 functions.
//////////////////////////////////////////////////////////////////////////////
inline DWORD MD5::I(DWORD x, DWORD y, DWORD z)
{
    return y ^(x | ~z);
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::FF
// Return type     : void 
// Argument        : DWORD& a
// Argument        : DWORD b
// Argument        : DWORD c
// Argument        : DWORD d
// Argument        : DWORD x
// Argument        : DWORD  s
// Argument        : DWORD ac
// Description     : 
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
//////////////////////////////////////////////////////////////////////////////
inline void MD5::FF(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD  s, DWORD ac)
{
    a += F(b, c, d) + x + ac;
    a = rotate_left(a, s) +b;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::GG
// Return type     : void 
// Argument        : DWORD& a
// Argument        : DWORD b
// Argument        : DWORD c
// Argument        : DWORD d
// Argument        : DWORD x
// Argument        : DWORD s
// Argument        : DWORD ac
// Description     : 
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
//////////////////////////////////////////////////////////////////////////////
inline void MD5::GG(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac)
{
    a += G(b, c, d) + x + ac;
    a = rotate_left(a, s) +b;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::HH
// Return type     : void 
// Argument        : DWORD& a
// Argument        : DWORD b
// Argument        : DWORD c
// Argument        : DWORD d
// Argument        : DWORD x
// Argument        : DWORD s
// Argument        : DWORD ac
// Description     : 
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
//////////////////////////////////////////////////////////////////////////////
inline void MD5::HH(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac)
{
    a += H(b, c, d) + x + ac;
    a = rotate_left(a, s) +b;
}
 
//////////////////////////////////////////////////////////////////////////////
// Function name   : MD5::II
// Return type     : void 
// Argument        : DWORD& a
// Argument        : DWORD b
// Argument        : DWORD c
// Argument        : DWORD d
// Argument        : DWORD x
// Argument        : DWORD s
// Argument        : DWORD ac
// Description     : 
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
//////////////////////////////////////////////////////////////////////////////
inline void MD5::II(DWORD& a, DWORD b, DWORD c, DWORD d, DWORD x, DWORD s, DWORD ac)
{
    a += I(b, c, d) + x + ac;
    a = rotate_left(a, s) +b;
}

kb/md5hashing.txt · 마지막으로 수정됨: 2014/11/10 19:49 (바깥 편집)