13 UInt32 func(UInt32, UInt32, UInt32);
16 inline UInt32 func<1>(UInt32 x, UInt32 y, UInt32 z)
18 return (y&x) | (z&~x);
22 inline UInt32 func<2>(UInt32 x, UInt32 y, UInt32 z)
24 return (x&z) | (y&~z);
28 inline UInt32 func<3>(UInt32 x, UInt32 y, UInt32 z)
34 inline UInt32 func<4>(UInt32 x, UInt32 y, UInt32 z)
39 inline UInt32 rotate_left(UInt32 x, UInt32 b)
41 return (x<<b) | (x>>(32-b));
47 UInt32 MD5::sin_table[64] = { 0 };
48 unsigned MD5::rotate_table[16] =
61 MD5::MD5(const char *data, unsigned len)
67 MD5::MD5(const string &str)
75 buffer[0] = 0x67452301;
76 buffer[1] = 0xefcdab89;
77 buffer[2] = 0x98badcfe;
78 buffer[3] = 0x10325476;
82 for(unsigned i=0; i<64; ++i)
83 sin_table[i] = 4294967296.0*abs(sin((i+1)*1.0));
86 unsigned MD5::get_digest(char *digest, unsigned len) const
89 throw invalid_argument("MD5::get_digest");
93 char padding[64] = { static_cast<char>(0x80) };
94 padded.update(padding, 64-(unprocessed_bytes+8)%64);
96 UInt64 message_length = (processed_bytes+unprocessed_bytes)*8;
97 for(unsigned i=0; i<8; ++i)
98 padding[i] = message_length>>(i*8);
99 padded.update(padding, 8);
101 for(unsigned i=0; i<16; ++i)
102 digest[i] = padded.buffer[i/4]>>((i%4)*8);
107 void MD5::process_block(const char *data)
109 UInt32 input_words[16];
111 const UInt8 *u8data = reinterpret_cast<const UInt8 *>(data);
112 for(unsigned i=0; i<16; ++i)
113 input_words[i] = (u8data[i*4+3]<<24) | (u8data[i*4+2]<<16) | (u8data[i*4+1]<<8) | u8data[i*4];
115 UInt32 work_buffer[4];
116 copy(buffer, buffer+4, work_buffer);
118 perform_round<1, 0, 1>(work_buffer, input_words);
119 perform_round<2, 1, 5>(work_buffer, input_words);
120 perform_round<3, 5, 3>(work_buffer, input_words);
121 perform_round<4, 0, 7>(work_buffer, input_words);
123 for(unsigned i=0; i<4; ++i)
124 buffer[i] += work_buffer[i];
126 processed_bytes += 64;
129 template<unsigned N, unsigned START, unsigned DELTA>
130 inline void MD5::perform_round(UInt32 *work_buffer, const UInt32 *input_words)
132 for(unsigned i=0; i<4; ++i)
133 for(unsigned j=0; j<4; ++j)
136 UInt32 &a = work_buffer[(4-j)&3];
137 UInt32 &b = work_buffer[(5-j)&3];
138 UInt32 &c = work_buffer[(6-j)&3];
139 UInt32 &d = work_buffer[(7-j)&3];
140 UInt32 sum = a + func<N>(b, c, d) + input_words[(START+k*DELTA)&15] + sin_table[(N-1)*16+k];
141 a = b + rotate_left(sum, rotate_table[(N-1)*4+j]);
145 } // namespace Crypto