Test results and Baidu Encyclopedia test examples are consistent.
The implementation of the need to note: The last four variables a B C D link to the results, attention to the order of the variable high and low, specific reference to Linkresult () method.
#include "md5.h"
#include <iostream>
using namespace Std;
const int S[4][4] = {7, 12, 17, 22,
5, 9, 14, 20,
4, 11, 16, 23,
6, 10, 15, 21};
void Md5::init ()
{
A = 0x67452301;
B = 0xefcdab89;
C = 0x98badcfe;
D = 0x10325476;
remainnum_ = 0;
Remain_[0] = ' the ';
Md5result_hex_[0] = ' the ';
Md5result_[0] = ' the ';
Totalinputbits_ = 0;
Isdone_ = false;
}
MD5::MD5 ()
{
Init ();
}
Inline Md5::uint32 md5::rotateleft (const uint32 x, int n)
{
return (x << N) | (x >> (32-n));
If X is signed, use: (x << N) | ((x & 0xFFFFFFFF) >> (32-n))
}
Inline Md5::uint32 md5::f (const uint32 x, const uint32 y, const UInt32 z)
{
Return (x & y) | ((~x) & Z);
}
Inline Md5::uint32 md5::g (const uint32 x, const uint32 y, const UInt32 z)
{
Return (X & Z) | (Y & (~z));
}
Inline Md5::uint32 md5::h (const uint32 x, const uint32 y, const UInt32 z)
{
return x ^ y ^ z;
}
Inline Md5::uint32 md5::i (const uint32 x, const uint32 y, const UInt32 z)
{
Return y ^ (x | (~z));
}
inline void Md5::ff (UInt32 &a, const UInt32 B, const uint32 C, const UInt32 D,
Const UINT32 MJ, const int s, const uint32 TI)
{
A = B + rotateleft (A + F (b, C, D) + Mj + ti, s);
}
inline void Md5::gg (UInt32 &a, const UInt32 B, const uint32 C, const UInt32 D,
Const UINT32 MJ, const int s, const uint32 TI)
{
A = B + rotateleft (A + G (b, C, D) + Mj + ti, s);
}
inline void Md5::hh (UInt32 &a, const UInt32 B, const uint32 C, const UInt32 D,
Const UINT32 MJ, const int s, const uint32 TI)
{
A = B + rotateleft (A + H (b, C, D) + Mj + ti, s);
}
inline void Md5::ii (UInt32 &a, const UInt32 B, const uint32 C, const UInt32 D,
Const UINT32 MJ, const int s, const uint32 TI)
{
A = B + rotateleft (A + I (b, C, D) + Mj + ti, s);
}
Link A B C D to result (bit style result and hexadecimal style result)
void Md5::linkresult ()
{
Bit style result
for (int i = 0; i < 4; i++)//link A:low to High
{
Md5result_[i] = (A >> 8*i) & 0xFF;
}
for (int i = 4; i<8; i++)//link B:low to High
{
Md5result_[i] = (B >> 8* (i-4)) & 0xFF;
}
for (int i = 8; i<12; i++)//link C:low to High
{
Md5result_[i] = (C >> 8* (i-8)) & 0xFF;
}
for (int i = i<16; i++)//link D:low to High
{
Md5result_[i] = (D >> 8* (i-12)) & 0xFF;
}
Change to hexadecimal style result
Note:it is not the same as simply link hex (A) Hex (B) Hex (C) Hex (D)
for (int i = 0; i < i++)
sprintf (& Md5result_hex_[i*2], "%02x", Md5result_[i]);
MD5RESULT_HEX_[32] = ' the ';
}
Print the MD5 by hex
void MD5::p rintMd5 ()
{
if (!isdone_)
{
cout<< "Error:computation is not finished" <<endl;
}
Else
cout<< "MD5 Value:" << md5result_hex_ <<endl;
}
Get the MD5 value of hex style
String Md5::getmd5 ()
{
if (!isdone_)
{
cout<< "Error:computation is not finished" <<endl;
Exit (0);
}
String A ((const char *) md5result_hex_);
return A;
}
void Md5::uchartouint (UInt32 output[], const UCHAR8 input[], const unsigned int translength)
{
for (int i = 0, j = 0; j < Translength; i++, j = 4)
{
Output[i] = ((UInt32) input[j]) | (((UInt32) input[j+1]) << 8) |
(((UInt32) input[j+2]) << 16) | (((UInt32) input[j+3]) << 24);
}
}
Four round on the A block of the bits;
void Md5::fourround (const UCHAR8 block[])
{
UInt32 A = a, B = b, c = c, d = D;
UInt32 m[16];
Uchartouint (M, block, Blocklen_); Blocklen_ is a const INT = 64;
Round 1
FF (A, B, C, D, m[0], s[0][0], 0xd76aa478);
FF (d, a, B, C, m[1], s[0][1], 0xe8c7b756);
FF (c, D, a, B, m[2], s[0][2], 0x242070db);
FF (b, C, D, A, m[3], s[0][3], 0xc1bdceee);
FF (A, B, C, D, m[4], s[0][0], 0XF57C0FAF);
FF (d, a, B, C, m[5], s[0][1], 0x4787c62a);
FF (c, D, a, B, m[6], s[0][2], 0xa8304613);
FF (b, C, D, A, m[7], s[0][3], 0xfd469501);
FF (A, B, C, D, m[8], s[0][0], 0X698098D8);
FF (d, a, B, C, m[9], s[0][1], 0X8B44F7AF);
FF (c, D, a, B, m[10], s[0][2], 0XFFFF5BB1);
FF (b, C, D, A, m[11], s[0][3], 0x895cd7be);
FF (A, B, C, D, m[12], s[0][0], 0x6b901122);
FF (d, a, B, C, m[13], s[0][1], 0xfd987193);
FF (c, D, a, B, m[14], s[0][2], 0xa679438e);
FF (b, C, D, A, m[15], s[0][3], 0x49b40821);
Round 2
GG (A, B, C, D, m[1], s[1][0], 0xf61e2562);
GG (d, a, B, C, m[6], s[1][1], 0xc040b340);
GG (c, D, a, B, m[11], s[1][2], 0x265e5a51);
GG (b, C, D, A, m[0], s[1][3], 0XE9B6C7AA);
GG (A, B, C, D, m[5], s[1][0], 0xd62f105d);
GG (d, a, B, C, m[10], s[1][1], 0x2441453);
GG (c, D, a, B, m[15], s[1][2], 0xd8a1e681);
GG (b, C, D, A, m[4], s[1][3], 0XE7D3FBC8);
GG (A, B, C, D, m[9], s[1][0], 0x21e1cde6);
GG (d, a, B, C, m[14], s[1][1], 0xc33707d6);
GG (c, D, a, B, m[3], s[1][2], 0xf4d50d87);
GG (b, C, D, A, m[8], s[1][3], 0x455a14ed);
GG (A, B, C, D, m[13], s[1][0], 0xa9e3e905);
GG (d, a, B, C, m[2], s[1][1], 0xfcefa3f8);
GG (c, D, a, B, m[7], s[1][2], 0x676f02d9);
GG (b, C, D, A, m[12], s[1][3], 0x8d2a4c8a);
Round 3
HH (A, B, C, D, m[5], s[2][0], 0xfffa3942);
HH (d, a, B, C, m[8], s[2][1], 0x8771f681);
HH (c, D, a, B, m[11], s[2][2], 0x6d9d6122);
HH (b, C, D, A, m[14], s[2][3], 0xfde5380c);
HH (A, B, C, D, m[1], s[2][0], 0xa4beea44);
HH (d, a, B, C, m[4], s[2][1], 0x4bdecfa9);
HH (c, D, a, B, m[7], s[2][2], 0xf6bb4b60);
HH (b, C, D, A, m[10], s[2][3], 0XBEBFBC70);
HH (A, B, C, D, m[13], s[2][0], 0x289b7ec6);
HH (d, a, B, C, m[0], s[2][1], 0XEAA127FA);
HH (c, D, a, B, m[3], s[2][2], 0xd4ef3085);
HH (b, C, D, A, m[6], s[2][3], 0x4881d05);
HH (A, B, C, D, m[9], s[2][0], 0xd9d4d039);
HH (d, a, B, C, m[12], s[2][1], 0xe6db99e5);
HH (c, D, a, B, m[15], s[2][2], 0x1fa27cf8);
HH (b, C, D, A, m[2], s[2][3], 0xc4ac5665);
Round 4
II (A, B, C, D, m[0], s[3][0], 0xf4292244);
II (d, a, B, C, m[7], s[3][1], 0x432aff97);
II (c, D, a, B, m[14], s[3][2], 0xab9423a7);
II (b, C, D, A, m[5], s[3][3], 0xfc93a039);
II (A, B, C, D, m[12], s[3][0], 0x655b59c3);
II (d, a, B, C, m[3], s[3][1], 0x8f0ccc92);
II (c, D, a, B, m[10], s[3][2], 0xffeff47d);
II (b, C, D, A, m[1], s[3][3], 0X85845DD1);
II (A, B, C, D, m[8], s[3][0], 0x6fa87e4f);
II (d, a, B, C, m[15], s[3][1], 0xfe2ce6e0);
II (c, D, a, B, m[6], s[3][2], 0xa3014314);
II (b, C, D, A, m[13], s[3][3], 0X4E0811A1);
II (A, B, C, D, m[4], s[3][0], 0xf7537e82);
II (d, a, B, C, m[11], s[3][1], 0xbd3af235);
II (c, D, a, B, m[2], s[3][2], 0X2AD7D2BB);
II (b, C, D, A, m[9], s[3][3], 0xeb86d391);
A + A;
B + B;
C + + C;
D + + D;
}
Update Md5,must consider the Remain_.
void Md5::updatemd5 (const UCHAR8 input[], const int length)
{
Isdone_ = false;
Totalinputbits_ + = (length << 3);
int start = Blocklen_-remainnum_; Blocklen_ = 64
Copy a part of input to remain_ so it can form a block (size=64)
if (start <= length)
{
Can form a block,then do fourround to this block
memcpy (&remain_[remainnum_], input, start);
Fourround (Remain_);
int i;
for (i = start; I <= length-blocklen_ i + = Blocklen_)
{
Fourround (&input[i]);
}
Remainnum_ = Length-i;
memcpy (Remain_, &input[i], remainnum_);
}
Else
{
Can not form a blocks, function return;
memcpy (&remain_[remainnum_], input, length);
remainnum_ = length;
}
}
void Md5::updatemd5 (const CHAR8 input[], const int length)
{
UPDATEMD5 ((const UCHAR8 *) input, length);
}
Padding with 100000 ... To Remain_ and add the 64bit original size of input
void Md5::finalize ()
{
if (Isdone_ = = True)
Return
Uchar8 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
};
int temp = 56-REMAINNUM_; 56 = 448/8
if (Temp > 0)
{
UPDATEMD5 (padding, temp);
Totalinputbits_-= (temp << 3);
}
else if (Temp < 0)
{
UpdateMd5 (padding, + temp);
Totalinputbits_-= ((+ temp) << 3);
}
Trans Totalinputbits_ to Uchar8 (64bits)
Uchar8 Bits[8];
for (int i = 0; i < 8; i++)
{
Bits[i] = (totalinputbits_ >> 8*i) & 0xFF;
}
UPDATEMD5 (Bits, 8); Add the number of original input (the last 64bits)
Linkresult ();
Isdone_ = true;
}
Comput the MD5 based on input, (just this one input)
void Md5::computmd5 (const UCHAR8 input[], const int length)
{
Init ();
UPDATEMD5 (input, length);
Finalize ();
}
void Md5::computmd5 (const CHAR8 input[], const int length)
{
COMPUTMD5 ((const UCHAR8 *) input, length);
}