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 + "\"") } }