사용자 도구

사이트 도구


kb:md5hashing

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:md5hashing [2014/11/10 19:49] (현재)
줄 1: 줄 1:
 +====== MD5 Hashing ======
 +MD5는 해쉬 알고리즘의 일종이다. 즉 문자열이나 파일 같은 것을 읽어들여서 이를 일정한 값으로 요악하는 알고리즘이다. 암호화와 관련해서 원문 확인용으로 쓰일 때가 있다. Win32에서도 사용가능한 함수가 있기는 하지만, [[Base64Encoding]]과 관련해서 인터넷을 뒤지다가 있길래 같이 만들어버렸다.
 +
 +
 +====== C++ Implementation ======
 +<file cpp 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__
 +</​file>​
 +
 +<file cpp 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;
 +}
 +</​file>​
 +
 +----
 +  * see also [[Cryptography]]
  
kb/md5hashing.txt · 마지막으로 수정됨: 2014/11/10 19:49 (바깥 편집)