Skip to content

Instantly share code, notes, and snippets.

@oyyq99999
Last active August 29, 2015 14:06
Show Gist options
  • Save oyyq99999/d353d29bd441dbc8f95e to your computer and use it in GitHub Desktop.
Save oyyq99999/d353d29bd441dbc8f95e to your computer and use it in GitHub Desktop.
md4 algo
package oyyq.test.hash.md4;
import static java.lang.String.format;
import java.util.Arrays;
public class Md4Hash {
private static final class Md4MagicNumberGenerator {
static int getMagicNumber(int x) {
return (int) ((long) (Math.sqrt(x) / 4L * Math.pow(2, 32)));
}
}
private static final int GG_MAGIC = Md4MagicNumberGenerator.getMagicNumber(2);
private static final int HH_MAGIC = Md4MagicNumberGenerator.getMagicNumber(3);
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) {
Md4Hash md4 = new Md4Hash();
md4.update("The".getBytes());
md4.update(" quick brown fox jumps over the lazy cog".getBytes());
md4.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 tmp = a + f(b, c, d) + xK;
return (tmp << s) | (tmp >>> (32 - s));
}
private static int g(int x, int y, int z) {
return (x & y) | (x & z) | (y & z);
}
private static int gg(int a, int b, int c, int d, int xK, int s) {
int tmp = a + g(b, c, d) + xK + GG_MAGIC;
return (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 tmp = a + h(b, c, d) + xK + HH_MAGIC;
return (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], 3);
d = ff(d, a, b, c, buf[1], 7);
c = ff(c, d, a, b, buf[2], 11);
b = ff(b, c, d, a, buf[3], 19);
a = ff(a, b, c, d, buf[4], 3);
d = ff(d, a, b, c, buf[5], 7);
c = ff(c, d, a, b, buf[6], 11);
b = ff(b, c, d, a, buf[7], 19);
a = ff(a, b, c, d, buf[8], 3);
d = ff(d, a, b, c, buf[9], 7);
c = ff(c, d, a, b, buf[10], 11);
b = ff(b, c, d, a, buf[11], 19);
a = ff(a, b, c, d, buf[12], 3);
d = ff(d, a, b, c, buf[13], 7);
c = ff(c, d, a, b, buf[14], 11);
b = ff(b, c, d, a, buf[15], 19);
// Round 2
a = gg(a, b, c, d, buf[0], 3);
d = gg(d, a, b, c, buf[4], 5);
c = gg(c, d, a, b, buf[8], 9);
b = gg(b, c, d, a, buf[12], 13);
a = gg(a, b, c, d, buf[1], 3);
d = gg(d, a, b, c, buf[5], 5);
c = gg(c, d, a, b, buf[9], 9);
b = gg(b, c, d, a, buf[13], 13);
a = gg(a, b, c, d, buf[2], 3);
d = gg(d, a, b, c, buf[6], 5);
c = gg(c, d, a, b, buf[10], 9);
b = gg(b, c, d, a, buf[14], 13);
a = gg(a, b, c, d, buf[3], 3);
d = gg(d, a, b, c, buf[7], 5);
c = gg(c, d, a, b, buf[11], 9);
b = gg(b, c, d, a, buf[15], 13);
// Round 3
a = hh(a, b, c, d, buf[0], 3);
d = hh(d, a, b, c, buf[8], 9);
c = hh(c, d, a, b, buf[4], 11);
b = hh(b, c, d, a, buf[12], 15);
a = hh(a, b, c, d, buf[2], 3);
d = hh(d, a, b, c, buf[10], 9);
c = hh(c, d, a, b, buf[6], 11);
b = hh(b, c, d, a, buf[14], 15);
a = hh(a, b, c, d, buf[1], 3);
d = hh(d, a, b, c, buf[9], 9);
c = hh(c, d, a, b, buf[5], 11);
b = hh(b, c, d, a, buf[13], 15);
a = hh(a, b, c, d, buf[3], 3);
d = hh(d, a, b, c, buf[11], 9);
c = hh(c, d, a, b, buf[7], 11);
b = hh(b, c, d, a, buf[15], 15);
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