Skip to content

Instantly share code, notes, and snippets.

@oyyq99999
Last active August 29, 2015 14:06
Show Gist options
  • Save oyyq99999/6968d127cfccd21264fa to your computer and use it in GitHub Desktop.
Save oyyq99999/6968d127cfccd21264fa to your computer and use it in GitHub Desktop.
md5 algo
package oyyq.test.hash.md5;
import static java.lang.String.format;
import java.util.Arrays;
public class Md5Hash {
private static final class Md5TTableGenerator {
private static int[] tTable = null;
static int[] getTTable() {
if (tTable == null) {
tTable = new int[65];
for (int i = 0; i < 65; i++) {
tTable[i] = (int) ((long) (4294967296L * Math.abs(Math.sin(i))));
}
}
return tTable.clone();
}
}
private static final int[] t = Md5TTableGenerator.getTTable();
private int a = 0x67452301;
private int b = 0xefcdab89;
private long bytesProcessed = 0L;
private int c = 0x98badcfe;
private int d = 0x10325476;
private int offset = 0;
private byte[] remaining = new byte[64];
public static void main(String[] args) {
Md5Hash md5 = new Md5Hash();
md5.update("The".getBytes());
md5.update(" quick brown fox jumps over the lazy dog.".getBytes());
md5.digest();
}
private static int f(int x, int y, int z) {
return (x & y) | ((~x) & z);
}
private static int ff(int a, int b, int c, int d, int xK, int s, int i) {
int tmp = a + f(b, c, d) + xK + t[i];
return b + ((tmp << s) | (tmp >>> (32 - s)));
}
private static int g(int x, int y, int z) {
return (x & z) | (y & (~z));
}
private static int gg(int a, int b, int c, int d, int xK, int s, int i) {
int tmp = a + g(b, c, d) + xK + t[i];
return b + ((tmp << s) | (tmp >>> (32 - s)));
}
private static int h(int x, int y, int z) {
return (x ^ y) ^ z;
}
private static int hh(int a, int b, int c, int d, int xK, int s, int i) {
int tmp = a + h(b, c, d) + xK + t[i];
return b + ((tmp << s) | (tmp >>> (32 - s)));
}
private static int i(int x, int y, int z) {
return y ^ (x | (~z));
}
private static int ii(int a, int b, int c, int d, int xK, int s, int i) {
int tmp = a + i(b, c, d) + xK + t[i];
return b + ((tmp << s) | (tmp >>> (32 - s)));
}
private static String toBigEndianHexString(int x) {
return format("%02x", x & 0xff) + format("%02x", (x >>> 8) & 0xff)
+ format("%02x", (x >>> 16) & 0xff) + format("%02x", (x >>> 24) & 0xff);
}
public void digest() {
padding();
System.out.println(toBigEndianHexString(a) + toBigEndianHexString(b)
+ toBigEndianHexString(c) + toBigEndianHexString(d));
}
public void reset() {
a = 0x67452301;
b = 0xefcdab89;
c = 0x98badcfe;
d = 0x10325476;
offset = 0;
bytesProcessed = 0L;
}
public void update(byte[] data) {
int off = 0;
byte[] byteBuf = new byte[64];
int[] buf = new int[16];
while (data.length >= off + 64 - offset) {
System.arraycopy(remaining, 0, byteBuf, 0, offset);
System.arraycopy(data, off, byteBuf, offset, 64 - offset);
off += 64 - offset;
offset = 0;
for (int i = 0; i < 16; i++) {
int j = i << 2;
buf[i] = (byteBuf[j] & 0xff) | ((byteBuf[j + 1] & 0xff) << 8)
| ((byteBuf[j + 2] & 0xff) << 16) | ((byteBuf[j + 3] & 0xff) << 24);
}
int aa = a;
int bb = b;
int cc = c;
int dd = d;
// Round 1
a = ff(a, b, c, d, buf[0], 7, 1);
d = ff(d, a, b, c, buf[1], 12, 2);
c = ff(c, d, a, b, buf[2], 17, 3);
b = ff(b, c, d, a, buf[3], 22, 4);
a = ff(a, b, c, d, buf[4], 7, 5);
d = ff(d, a, b, c, buf[5], 12, 6);
c = ff(c, d, a, b, buf[6], 17, 7);
b = ff(b, c, d, a, buf[7], 22, 8);
a = ff(a, b, c, d, buf[8], 7, 9);
d = ff(d, a, b, c, buf[9], 12, 10);
c = ff(c, d, a, b, buf[10], 17, 11);
b = ff(b, c, d, a, buf[11], 22, 12);
a = ff(a, b, c, d, buf[12], 7, 13);
d = ff(d, a, b, c, buf[13], 12, 14);
c = ff(c, d, a, b, buf[14], 17, 15);
b = ff(b, c, d, a, buf[15], 22, 16);
// Round 2
a = gg(a, b, c, d, buf[1], 5, 17);
d = gg(d, a, b, c, buf[6], 9, 18);
c = gg(c, d, a, b, buf[11], 14, 19);
b = gg(b, c, d, a, buf[0], 20, 20);
a = gg(a, b, c, d, buf[5], 5, 21);
d = gg(d, a, b, c, buf[10], 9, 22);
c = gg(c, d, a, b, buf[15], 14, 23);
b = gg(b, c, d, a, buf[4], 20, 24);
a = gg(a, b, c, d, buf[9], 5, 25);
d = gg(d, a, b, c, buf[14], 9, 26);
c = gg(c, d, a, b, buf[3], 14, 27);
b = gg(b, c, d, a, buf[8], 20, 28);
a = gg(a, b, c, d, buf[13], 5, 29);
d = gg(d, a, b, c, buf[2], 9, 30);
c = gg(c, d, a, b, buf[7], 14, 31);
b = gg(b, c, d, a, buf[12], 20, 32);
// Round 3
a = hh(a, b, c, d, buf[5], 4, 33);
d = hh(d, a, b, c, buf[8], 11, 34);
c = hh(c, d, a, b, buf[11], 16, 35);
b = hh(b, c, d, a, buf[14], 23, 36);
a = hh(a, b, c, d, buf[1], 4, 37);
d = hh(d, a, b, c, buf[4], 11, 38);
c = hh(c, d, a, b, buf[7], 16, 39);
b = hh(b, c, d, a, buf[10], 23, 40);
a = hh(a, b, c, d, buf[13], 4, 41);
d = hh(d, a, b, c, buf[0], 11, 42);
c = hh(c, d, a, b, buf[3], 16, 43);
b = hh(b, c, d, a, buf[6], 23, 44);
a = hh(a, b, c, d, buf[9], 4, 45);
d = hh(d, a, b, c, buf[12], 11, 46);
c = hh(c, d, a, b, buf[15], 16, 47);
b = hh(b, c, d, a, buf[2], 23, 48);
// Round 4
a = ii(a, b, c, d, buf[0], 6, 49);
d = ii(d, a, b, c, buf[7], 10, 50);
c = ii(c, d, a, b, buf[14], 15, 51);
b = ii(b, c, d, a, buf[5], 21, 52);
a = ii(a, b, c, d, buf[12], 6, 53);
d = ii(d, a, b, c, buf[3], 10, 54);
c = ii(c, d, a, b, buf[10], 15, 55);
b = ii(b, c, d, a, buf[1], 21, 56);
a = ii(a, b, c, d, buf[8], 6, 57);
d = ii(d, a, b, c, buf[15], 10, 58);
c = ii(c, d, a, b, buf[6], 15, 59);
b = ii(b, c, d, a, buf[13], 21, 60);
a = ii(a, b, c, d, buf[4], 6, 61);
d = ii(d, a, b, c, buf[11], 10, 62);
c = ii(c, d, a, b, buf[2], 15, 63);
b = ii(b, c, d, a, buf[9], 21, 64);
a += aa;
b += bb;
c += cc;
d += dd;
}
if (data.length > off) {
System.arraycopy(data, off, remaining, offset, data.length - off);
offset += data.length - off;
}
bytesProcessed += data.length;
}
private void padding() {
int padLen = (int) (64 - bytesProcessed & 0x3f);
if (padLen <= 8) {
padLen += 64;
}
byte[] pad = new byte[padLen];
Arrays.fill(pad, (byte) 0);
pad[0] = (byte) 0x80;
long bitLength = bytesProcessed << 3;
int i = padLen - 8;
pad[i++] = (byte) (bitLength & 0xff);
pad[i++] = (byte) ((bitLength >>> 8) & 0xff);
pad[i++] = (byte) ((bitLength >>> 16) & 0xff);
pad[i++] = (byte) ((bitLength >>> 24) & 0xff);
pad[i++] = (byte) ((bitLength >>> 32) & 0xff);
pad[i++] = (byte) ((bitLength >>> 40) & 0xff);
pad[i++] = (byte) ((bitLength >>> 48) & 0xff);
pad[i++] = (byte) ((bitLength >>> 56) & 0xff);
update(pad);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment