MD5/Implementation: Difference between revisions
Content added Content deleted
(Adding a groovy version (minor syntactic changes from the Java version)) |
|||
Line 1,725: | Line 1,725: | ||
57edf4a22be3c955ac49da2e2107b67a |
57edf4a22be3c955ac49da2e2107b67a |
||
</pre> |
</pre> |
||
=={{header|Groovy}}== |
|||
<lang groovy> |
|||
class MD5 { |
|||
private static final int INIT_A = 0x67452301 |
|||
private static final int INIT_B = (int)0xEFCDAB89L |
|||
private static final int INIT_C = (int)0x98BADCFEL |
|||
private static final int INIT_D = 0x10325476 |
|||
private static final int[] SHIFT_AMTS = [ |
|||
7, 12, 17, 22, |
|||
5, 9, 14, 20, |
|||
4, 11, 16, 23, |
|||
6, 10, 15, 21 |
|||
] |
|||
private static final int[] TABLE_T = new int[64] |
|||
static |
|||
{ |
|||
for (int i in 0..63) |
|||
TABLE_T[i] = (int)(long)((1L << 32) * Math.abs(Math.sin(i + 1))) |
|||
} |
|||
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 in 0..7) |
|||
{ |
|||
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 in 0..(numBlocks - 1)) |
|||
{ |
|||
int index = i << 6 |
|||
for (int j in 0..63) { |
|||
buffer[j >>> 2] = ((int) ((index < messageLenBytes) ? message[index] : paddingBytes[index - messageLenBytes]) << 24) | (buffer[j >>> 2] >>> 8) |
|||
index++ |
|||
} |
|||
int originalA = a |
|||
int originalB = b |
|||
int originalC = c |
|||
int originalD = d |
|||
for (int j in 0..63) |
|||
{ |
|||
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 in 0..3) |
|||
{ |
|||
int n = (i == 0) ? a : ((i == 1) ? b : ((i == 2) ? c : d)) |
|||
for (int j in 0..3) |
|||
{ |
|||
md5[count++] = (byte)n |
|||
n >>>= 8 |
|||
} |
|||
} |
|||
return md5 |
|||
} |
|||
static String toHexString(byte[] b) |
|||
{ |
|||
StringBuilder sb = new StringBuilder() |
|||
for (int i in 0..(b.length - 1)) |
|||
{ |
|||
sb.append(String.format("%02X", b[i] & 0xFF)) |
|||
} |
|||
return sb.toString() |
|||
} |
|||
static void main(String[] args) |
|||
{ |
|||
String[] testStrings = ["", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", |
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", |
|||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890" ] |
|||
for (String s : testStrings) |
|||
System.out.println("0x" + toHexString(computeMD5(s.getBytes())) + " <== \"" + s + "\"") |
|||
} |
|||
} |
|||
</lang> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
<lang haskell>import Control.Monad (replicateM) |
<lang haskell>import Control.Monad (replicateM) |