Jump to content

MD5/Implementation: Difference between revisions

Added Java version
(Move Modula-3 MD5 implementation here)
(Added Java version)
Line 386:
57edf4a22be3c955ac49da2e2107b67a
</lang>
 
 
=={{header|Java}}==
 
Based on RFC-1321.
<lang java>
class MD5
{
 
private static int INIT_A = 0x67452301;
private static int INIT_B = (int)0xEFCDAB89L;
private static int INIT_C = (int)0x98BADCFEL;
private static int INIT_D = 0x10325476;
private static int[] SHIFT_AMTS = new int[] {
7, 12, 17, 22,
5, 9, 14, 20,
4, 11, 16, 23,
6, 10, 15, 21
};
private static int[] TABLE_T = new int[64];
static
{
for (int i = 0; i < 64; i++)
TABLE_T[i] = scaleToInt(Math.abs(Math.sin(i + 1)));
}
 
private static int scaleToInt(double d)
{
// Converts IEEE-754 double from 0 to 1.0 to the range of an unsigned int
long n = Double.doubleToLongBits(d);
long exponent = (n >>> 52) & 0x7FF;
long fraction = (n & 0xFFFFFFFFFFFFFL) | 0x10000000000000L;
return (int)(fraction >>> (1043 - exponent));
}
public static byte[] computeMD5(byte[] message)
{
int messageLenBytes = message.length;
int numBlocks = ((messageLenBytes + 8) >>> 6) + 1;
int totalLen = numBlocks << 6;
byte[] paddingBytes = new byte[totalLen - messageLenBytes];
paddingBytes[0] = (byte)0x80;
long messageLenBits = (long)messageLenBytes << 3;
for (int i = 0; i < 8; i++)
{
paddingBytes[paddingBytes.length - 8 + i] = (byte)messageLenBits;
messageLenBits >>>= 8;
}
int a = INIT_A;
int b = INIT_B;
int c = INIT_C;
int d = INIT_D;
int[] buffer = new int[16];
for (int i = 0; i < numBlocks; i ++)
{
int index = i << 6;
for (int j = 0; j < 64; j++, index++)
buffer[j >>> 2] = ((int)((index < messageLenBytes) ? message[index] : paddingBytes[index - messageLenBytes]) << 24) | (buffer[j >>> 2] >>> 8);
int originalA = a;
int originalB = b;
int originalC = c;
int originalD = d;
for (int j = 0; j < 64; j++)
{
int mod16 = j & 0x0F;
int div16 = j >>> 4;
int f = 0;
int bufferIndex = j;
switch (div16)
{
case 0:
f = (b & c) | (~b & d);
break;
case 1:
f = (b & d) | (c & ~d);
bufferIndex = (bufferIndex * 5 + 1) & 0x0F;
break;
case 2:
f = b ^ c ^ d;
bufferIndex = (bufferIndex * 3 + 5) & 0x0F;
break;
case 3:
f = c ^ (b | ~d);
bufferIndex = (bufferIndex * 7) & 0x0F;
break;
}
int temp = b + Integer.rotateLeft(a + f + buffer[bufferIndex] + TABLE_T[j], SHIFT_AMTS[(div16 << 2) | (j & 3)]);
a = d;
d = c;
c = b;
b = temp;
}
a += originalA;
b += originalB;
c += originalC;
d += originalD;
}
byte[] md5 = new byte[16];
int count = 0;
for (int i = 0; i < 4; i++)
{
int n = (i == 0) ? a : ((i == 1) ? b : ((i == 2) ? c : d));
for (int j = 0; j < 4; j++)
{
md5[count++] = (byte)n;
n >>>= 8;
}
}
return md5;
}
public static String toHexString(byte[] b)
{
StringBuilder sb = new StringBuilder();
String HEX_CHARS = "0123456789ABCDEF";
for (int i = 0; i < b.length; i++)
{
int n = (int)b[i] & 0xFF;
sb.append(HEX_CHARS.charAt(n >>> 4)).append(HEX_CHARS.charAt(n & 0x0F));
}
return sb.toString();
}
 
public static void main(String[] args)
{
String[] testStrings = new String[] { "", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890" };
for (String s : testStrings)
System.out.println("0x" + toHexString(computeMD5(s.getBytes())) + " <== \"" + s + "\"");
return;
}
}
</lang>
 
<b>Output:</b>
<pre>0xD41D8CD98F00B204E9800998ECF8427E <== ""
0x0CC175B9C0F1B6A831C399E269772661 <== "a"
0x900150983CD24FB0D6963F7D28E17F72 <== "abc"
0xF96B697D7CB7938D525A2F31AAF161D0 <== "message digest"
0xC3FCD3D76192E4007DFB496CCA67E13B <== "abcdefghijklmnopqrstuvwxyz"
0xD174AB98D277D9F5A5611C2C9F419D9F <== "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
0x57EDF4A22BE3C955AC49DA2E2107B67A <== "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
</pre>
 
 
=={{header|Modula-3}}==
Cookies help us deliver our services. By using our services, you agree to our use of cookies.