Class NAMESPACE_MD5
{
protected static uint F (uint B, uint C, uint D) { return (B & C) | (~B & D); }
protected static uint G (uint B, uint C, uint D) { return (B & D) | (C & ~D); }
protected static uint H (uint B, uint C, uint D) { return B ^ C ^ D; }
protected static uint I (uint B, uint C, uint D) { return C ^ (B | ~D); }
protected static uint leftrotate (uint x, uint c) { return (x << c) | (x >> (32-c)); }
protected static uint swapByte (uint x)
{
uint r = 0;
for(int i=0; i<8; i++)
r += ((x>>i) & 1) << (7-i);
return r;
}
protected static uint swapWord (uint x)
{
uint r = 0;
for(int i=0; i<32; i += 8)
r += ((x>>i) & 0xFF) << (24-i);
return r;
}
static string Hash(string key)
{
uint s[64] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 };
uint K[64] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
uint a0 = 0x67452301; uint b0 = 0xefcdab89; uint c0 = 0x98badcfe; uint d0 = 0x10325476;
Array<uint> input;
for(uint i=0; i < key.length(); i++)
{
input.push(key.ByteAt(i));
}
input.push(0x80);
while( input.size()%64 != 56 )
{
input.push(0x00);
}
uint strLen = 8*key.length();
for(uint i=0; i<8; i++)
{
input.push(strLen & 0xFF);
strLen >>= 8;
}
uint inputSize = uint(input.size());
for(uint i=0; i < inputSize; i++)
{
input[i] = swapByte(input[i]);
}
for(uint front=0; front < inputSize; front += 64)
{
Array<uint> M;
for(int k=0; k<64; k += 4)
{
M.push(
( swapByte(input[front + k + 0]) << 0 ) +
( swapByte(input[front + k + 1]) << 8 ) +
( swapByte(input[front + k + 2]) << 16) +
( swapByte(input[front + k + 3]) << 24)
);
}
uint A = a0;
uint B = b0;
uint C = c0;
uint D = d0;
uint f;
uint g;
for(uint i=0; i<64; i++)
{
if(0 <= i && i <= 15)
{
f = F(B,C,D);
g = i;
}
else if(16 <= i && i <= 31)
{
f = G(B,C,D);
g = (5*i+1)%16;
}
else if(32 <= i && i <= 47)
{
f = H(B,C,D);
g = (3*i+5)%16;
}
else {
f = I(B,C,D);
g = (7*i)%16;
}
f = f + A + K[i] + M[g];
A = D;
D = C;
C = B;
B = B + leftrotate(f, s[i]);
}
a0 += A;
b0 += B;
c0 += C;
d0 += D;
}
return string.format("%08x%08x%08x%08x",swapWord(a0),swapWord(b0),swapWord(c0),swapWord(d0));
}
}