import java.io.*;
import java.net.*;
import java.util.*;
import java.math.*;// This class computes MD5 hashes.
// Manually translated by Jon Howell <[email protected]>
// from some public domain C code (md5.c) included with the ssh-1.2.22 source.
// Tue Jan 19 15:55:50 EST 1999
// $Id: MD5.java,v 1.3 1999/01/19 21:30:11 jonh Exp jonh $
//
// To compute the message digest of a chunk of bytes, create an
// MD5 object 'md5', call md5.update() as needed on buffers full
// of bytes, and then call md5.md5final(), which
// will fill a supplied 16-byte array with the digest.
//
// A main() method is included that hashes the data on System.in.
//
// It seems to run around 25-30 times slower (JDK1.1.6) than optimized C
// (gcc -O4, version 2.7.2.3). Measured on a Sun Ultra 5 (SPARC 270MHz).
//
// Comments from md5.c from ssh-1.2.22, the basis for this code:
//
/* This code has been heavily hacked by Tatu Ylonen <[email protected]> to
make it compile on machines like Cray that don't have a 32 bit integer
type. */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/public class MD5 {
int buf[]; // These were originally unsigned ints.
// This Java code makes an effort to avoid sign traps.
// buf[] is where the hash accumulates.
long bits; // This is the count of bits hashed so far.
byte in[]; // This is a buffer where we stash bytes until we have
// enough (64) to perform a transform operation.
int inint[];
// inint[] used and discarded inside transform(),
// but why allocate it over and over?
// (In the C version this is allocated on the stack.) public MD5() {
buf = new int[4];
// fill the hash accumulator with a seed value
buf[0] = 0x67452301;
buf[1] = 0xefcdab89;
buf[2] = 0x98badcfe;
buf[3] = 0x10325476; // initially, we've hashed zero bits
bits = 0L; in = new byte[64];
inint = new int[16];
} public void update(byte[] newbuf) {
update(newbuf, 0, newbuf.length);
} public void update(byte[] newbuf, int length) {
update(newbuf, 0, length);
} public void update(byte[] newbuf, int bufstart, int buflen) {
int t;
int len = buflen; // shash old bits value for the "Bytes already in" computation
// just below.
t = (int) bits; // (int) cast should just drop high bits, I hope /* update bitcount */
/* the C code used two 32-bit ints separately, and carefully
* ensured that the carry carried.
* Java has a 64-bit long, which is just what the code really wants.
*/
bits += (long)(len<<3); t = (t >>> 3) & 0x3f; /* Bytes already in this->in */ /* Handle any leading odd-sized chunks */
/* (that is, any left-over chunk left by last update() */ if (t!=0) {
int p = t;
t = 64 - t;
if (len < t) {
System.arraycopy(newbuf, bufstart, in, p, len);
return;
}
System.arraycopy(newbuf, bufstart, in, p, t);
transform();
bufstart += t;
len -= t;
} /* Process data in 64-byte chunks */
while (len >= 64) {
System.arraycopy(newbuf, bufstart, in, 0, 64);
transform();
bufstart += 64;
len -= 64;
} /* Handle any remaining bytes of data. */
/* that is, stash them for the next update(). */
System.arraycopy(newbuf, bufstart, in, 0, len);
} /*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
public void md5final(byte[] digest) {
/* "final" is a poor method name in Java. :v) */
int count;
int p; // in original code, this is a pointer; in this java code
// it's an index into the array this->in. /* Compute number of bytes mod 64 */
count = (int) ((bits >>> 3) & 0x3F);
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = count;
in[p++] = (byte) 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
zeroByteArray(in, p, count);
transform();
/* Now fill the next block with 56 bytes */
zeroByteArray(in, 0, 56);
} else {
/* Pad block to 56 bytes */
zeroByteArray(in, p, count - 8);
}
/* Append length in bits and transform */
// Could use a PUT_64BIT... func here. This is a fairly
// direct translation from the C code, where bits was an array
// of two 32-bit ints.
int lowbits = (int) bits;
int highbits = (int) (bits >>> 32);
PUT_32BIT_LSB_FIRST(in, 56, lowbits);
PUT_32BIT_LSB_FIRST(in, 60, highbits);
transform();
PUT_32BIT_LSB_FIRST(digest, 0, buf[0]);
PUT_32BIT_LSB_FIRST(digest, 4, buf[1]);
PUT_32BIT_LSB_FIRST(digest, 8, buf[2]);
PUT_32BIT_LSB_FIRST(digest, 12, buf[3]); /* zero sensitive data */
/* notice this misses any sneaking out on the stack. The C
* version uses registers in some spots, perhaps because
* they care about this.
*/
zeroByteArray(in);
zeroIntArray(buf);
bits = 0;
zeroIntArray(inint);
}//下边还有
import java.net.*;
import java.util.*;
import java.math.*;// This class computes MD5 hashes.
// Manually translated by Jon Howell <[email protected]>
// from some public domain C code (md5.c) included with the ssh-1.2.22 source.
// Tue Jan 19 15:55:50 EST 1999
// $Id: MD5.java,v 1.3 1999/01/19 21:30:11 jonh Exp jonh $
//
// To compute the message digest of a chunk of bytes, create an
// MD5 object 'md5', call md5.update() as needed on buffers full
// of bytes, and then call md5.md5final(), which
// will fill a supplied 16-byte array with the digest.
//
// A main() method is included that hashes the data on System.in.
//
// It seems to run around 25-30 times slower (JDK1.1.6) than optimized C
// (gcc -O4, version 2.7.2.3). Measured on a Sun Ultra 5 (SPARC 270MHz).
//
// Comments from md5.c from ssh-1.2.22, the basis for this code:
//
/* This code has been heavily hacked by Tatu Ylonen <[email protected]> to
make it compile on machines like Cray that don't have a 32 bit integer
type. */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/public class MD5 {
int buf[]; // These were originally unsigned ints.
// This Java code makes an effort to avoid sign traps.
// buf[] is where the hash accumulates.
long bits; // This is the count of bits hashed so far.
byte in[]; // This is a buffer where we stash bytes until we have
// enough (64) to perform a transform operation.
int inint[];
// inint[] used and discarded inside transform(),
// but why allocate it over and over?
// (In the C version this is allocated on the stack.) public MD5() {
buf = new int[4];
// fill the hash accumulator with a seed value
buf[0] = 0x67452301;
buf[1] = 0xefcdab89;
buf[2] = 0x98badcfe;
buf[3] = 0x10325476; // initially, we've hashed zero bits
bits = 0L; in = new byte[64];
inint = new int[16];
} public void update(byte[] newbuf) {
update(newbuf, 0, newbuf.length);
} public void update(byte[] newbuf, int length) {
update(newbuf, 0, length);
} public void update(byte[] newbuf, int bufstart, int buflen) {
int t;
int len = buflen; // shash old bits value for the "Bytes already in" computation
// just below.
t = (int) bits; // (int) cast should just drop high bits, I hope /* update bitcount */
/* the C code used two 32-bit ints separately, and carefully
* ensured that the carry carried.
* Java has a 64-bit long, which is just what the code really wants.
*/
bits += (long)(len<<3); t = (t >>> 3) & 0x3f; /* Bytes already in this->in */ /* Handle any leading odd-sized chunks */
/* (that is, any left-over chunk left by last update() */ if (t!=0) {
int p = t;
t = 64 - t;
if (len < t) {
System.arraycopy(newbuf, bufstart, in, p, len);
return;
}
System.arraycopy(newbuf, bufstart, in, p, t);
transform();
bufstart += t;
len -= t;
} /* Process data in 64-byte chunks */
while (len >= 64) {
System.arraycopy(newbuf, bufstart, in, 0, 64);
transform();
bufstart += 64;
len -= 64;
} /* Handle any remaining bytes of data. */
/* that is, stash them for the next update(). */
System.arraycopy(newbuf, bufstart, in, 0, len);
} /*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
public void md5final(byte[] digest) {
/* "final" is a poor method name in Java. :v) */
int count;
int p; // in original code, this is a pointer; in this java code
// it's an index into the array this->in. /* Compute number of bytes mod 64 */
count = (int) ((bits >>> 3) & 0x3F);
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = count;
in[p++] = (byte) 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
zeroByteArray(in, p, count);
transform();
/* Now fill the next block with 56 bytes */
zeroByteArray(in, 0, 56);
} else {
/* Pad block to 56 bytes */
zeroByteArray(in, p, count - 8);
}
/* Append length in bits and transform */
// Could use a PUT_64BIT... func here. This is a fairly
// direct translation from the C code, where bits was an array
// of two 32-bit ints.
int lowbits = (int) bits;
int highbits = (int) (bits >>> 32);
PUT_32BIT_LSB_FIRST(in, 56, lowbits);
PUT_32BIT_LSB_FIRST(in, 60, highbits);
transform();
PUT_32BIT_LSB_FIRST(digest, 0, buf[0]);
PUT_32BIT_LSB_FIRST(digest, 4, buf[1]);
PUT_32BIT_LSB_FIRST(digest, 8, buf[2]);
PUT_32BIT_LSB_FIRST(digest, 12, buf[3]); /* zero sensitive data */
/* notice this misses any sneaking out on the stack. The C
* version uses registers in some spots, perhaps because
* they care about this.
*/
zeroByteArray(in);
zeroIntArray(buf);
bits = 0;
zeroIntArray(inint);
}//下边还有
// This main() method was created to easily test
// this class. It hashes whatever's on System.in. byte buf[] = new byte[397];
// arbitrary buffer length designed to irritate update()
int rc;
MD5 md = new MD5();
byte out[] = new byte[16];
int i;
int len = 0; try {
while ((rc = System.in.read(buf, 0, 397)) > 0) {
md.update(buf, rc);
len += rc;
}
} catch (IOException ex) {
ex.printStackTrace();
return;
}
md.md5final(out); System.out.println("file length: "+len);
System.out.println("hash: "+dumpBytes(out));
}
/////////////////////////////////////////////////////////////////////
// Below here ye will only finde private functions //
///////////////////////////////////////////////////////////////////// // There must be a way to do these functions that's
// built into Java, and I just haven't noticed it yet. private void zeroByteArray(byte[] a) {
zeroByteArray(a, 0, a.length);
} private void zeroByteArray(byte[] a, int start, int length) {
setByteArray(a, (byte) 0, start, length);
} private void setByteArray(byte[] a, byte val, int start, int length) {
int i;
int end = start+length;
for (i=start; i<end; i++) {
a[i] = val;
}
} private void zeroIntArray(int[] a) {
zeroIntArray(a, 0, a.length);
} private void zeroIntArray(int[] a, int start, int length) {
setIntArray(a, (int) 0, start, length);
} private void setIntArray(int[] a, int val, int start, int length) {
int i;
int end = start+length;
for (i=start; i<end; i++) {
a[i] = val;
}
}
// In the C version, a call to MD5STEP is a macro-in-a-macro.
// In this Java version, we pass an Fcore object to represent the
// inner macro, and the MD5STEP() method performs the work of
// the outer macro. It would be good if this could all get
// inlined, but it would take a pretty aggressive compiler to
// inline away the dynamic method lookup made by MD5STEP to
// get to the Fcore.f function. private abstract class Fcore {
abstract int f(int x, int y, int z);
}
private Fcore F1 = new Fcore() {
int f(int x, int y, int z) { return (z ^ (x & (y ^ z))); }};
private Fcore F2 = new Fcore() {
int f(int x, int y, int z) { return (y ^ (z & (x ^ y))); }};
private Fcore F3 = new Fcore() {
int f(int x, int y, int z) { return (x ^ y ^ z); }};
private Fcore F4 = new Fcore() {
int f(int x, int y, int z) { return (y ^ (x | ~z)); }}; private int MD5STEP(Fcore f, int w, int x, int y, int z, int data, int s) {
w += f.f(x, y, z) + data;
w = w<<s | w>>>(32-s);
w += x;
return w;
} private void transform() {
/* load in[] byte array into an internal int array */
int i;
int[] inint = new int[16]; for (i=0; i<16; i++) {
inint[i] = GET_32BIT_LSB_FIRST(in, 4*i);
} int a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3]; a = MD5STEP(F1, a, b, c, d, inint[0] + 0xd76aa478, 7);
d = MD5STEP(F1, d, a, b, c, inint[1] + 0xe8c7b756, 12);
c = MD5STEP(F1, c, d, a, b, inint[2] + 0x242070db, 17);
b = MD5STEP(F1, b, c, d, a, inint[3] + 0xc1bdceee, 22);
a = MD5STEP(F1, a, b, c, d, inint[4] + 0xf57c0faf, 7);
d = MD5STEP(F1, d, a, b, c, inint[5] + 0x4787c62a, 12);
c = MD5STEP(F1, c, d, a, b, inint[6] + 0xa8304613, 17);
b = MD5STEP(F1, b, c, d, a, inint[7] + 0xfd469501, 22);
a = MD5STEP(F1, a, b, c, d, inint[8] + 0x698098d8, 7);
d = MD5STEP(F1, d, a, b, c, inint[9] + 0x8b44f7af, 12);
c = MD5STEP(F1, c, d, a, b, inint[10] + 0xffff5bb1, 17);
b = MD5STEP(F1, b, c, d, a, inint[11] + 0x895cd7be, 22);
a = MD5STEP(F1, a, b, c, d, inint[12] + 0x6b901122, 7);
d = MD5STEP(F1, d, a, b, c, inint[13] + 0xfd987193, 12);
c = MD5STEP(F1, c, d, a, b, inint[14] + 0xa679438e, 17);
b = MD5STEP(F1, b, c, d, a, inint[15] + 0x49b40821, 22);
a = MD5STEP(F2, a, b, c, d, inint[1] + 0xf61e2562, 5);
d = MD5STEP(F2, d, a, b, c, inint[6] + 0xc040b340, 9);
c = MD5STEP(F2, c, d, a, b, inint[11] + 0x265e5a51, 14);
b = MD5STEP(F2, b, c, d, a, inint[0] + 0xe9b6c7aa, 20);
a = MD5STEP(F2, a, b, c, d, inint[5] + 0xd62f105d, 5);
d = MD5STEP(F2, d, a, b, c, inint[10] + 0x02441453, 9);
c = MD5STEP(F2, c, d, a, b, inint[15] + 0xd8a1e681, 14);
b = MD5STEP(F2, b, c, d, a, inint[4] + 0xe7d3fbc8, 20);
a = MD5STEP(F2, a, b, c, d, inint[9] + 0x21e1cde6, 5);
d = MD5STEP(F2, d, a, b, c, inint[14] + 0xc33707d6, 9);
c = MD5STEP(F2, c, d, a, b, inint[3] + 0xf4d50d87, 14);
b = MD5STEP(F2, b, c, d, a, inint[8] + 0x455a14ed, 20);
a = MD5STEP(F2, a, b, c, d, inint[13] + 0xa9e3e905, 5);
d = MD5STEP(F2, d, a, b, c, inint[2] + 0xfcefa3f8, 9);
c = MD5STEP(F2, c, d, a, b, inint[7] + 0x676f02d9, 14);
b = MD5STEP(F2, b, c, d, a, inint[12] + 0x8d2a4c8a, 20);
a = MD5STEP(F3, a, b, c, d, inint[5] + 0xfffa3942, 4);
d = MD5STEP(F3, d, a, b, c, inint[8] + 0x8771f681, 11);
c = MD5STEP(F3, c, d, a, b, inint[11] + 0x6d9d6122, 16);
b = MD5STEP(F3, b, c, d, a, inint[14] + 0xfde5380c, 23);
a = MD5STEP(F3, a, b, c, d, inint[1] + 0xa4beea44, 4);
d = MD5STEP(F3, d, a, b, c, inint[4] + 0x4bdecfa9, 11);
c = MD5STEP(F3, c, d, a, b, inint[7] + 0xf6bb4b60, 16);
b = MD5STEP(F3, b, c, d, a, inint[10] + 0xbebfbc70, 23);
a = MD5STEP(F3, a, b, c, d, inint[13] + 0x289b7ec6, 4);
d = MD5STEP(F3, d, a, b, c, inint[0] + 0xeaa127fa, 11);
c = MD5STEP(F3, c, d, a, b, inint[3] + 0xd4ef3085, 16);
b = MD5STEP(F3, b, c, d, a, inint[6] + 0x04881d05, 23);
a = MD5STEP(F3, a, b, c, d, inint[9] + 0xd9d4d039, 4);
d = MD5STEP(F3, d, a, b, c, inint[12] + 0xe6db99e5, 11);
c = MD5STEP(F3, c, d, a, b, inint[15] + 0x1fa27cf8, 16);
b = MD5STEP(F3, b, c, d, a, inint[2] + 0xc4ac5665, 23);
a = MD5STEP(F4, a, b, c, d, inint[0] + 0xf4292244, 6);
d = MD5STEP(F4, d, a, b, c, inint[7] + 0x432aff97, 10);
c = MD5STEP(F4, c, d, a, b, inint[14] + 0xab9423a7, 15);
b = MD5STEP(F4, b, c, d, a, inint[5] + 0xfc93a039, 21);
a = MD5STEP(F4, a, b, c, d, inint[12] + 0x655b59c3, 6);
d = MD5STEP(F4, d, a, b, c, inint[3] + 0x8f0ccc92, 10);
c = MD5STEP(F4, c, d, a, b, inint[10] + 0xffeff47d, 15);
b = MD5STEP(F4, b, c, d, a, inint[1] + 0x85845dd1, 21);
a = MD5STEP(F4, a, b, c, d, inint[8] + 0x6fa87e4f, 6);
d = MD5STEP(F4, d, a, b, c, inint[15] + 0xfe2ce6e0, 10);
c = MD5STEP(F4, c, d, a, b, inint[6] + 0xa3014314, 15);
b = MD5STEP(F4, b, c, d, a, inint[13] + 0x4e0811a1, 21);
a = MD5STEP(F4, a, b, c, d, inint[4] + 0xf7537e82, 6);
d = MD5STEP(F4, d, a, b, c, inint[11] + 0xbd3af235, 10);
c = MD5STEP(F4, c, d, a, b, inint[2] + 0x2ad7d2bb, 15);
b = MD5STEP(F4, b, c, d, a, inint[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
} private int GET_32BIT_LSB_FIRST(byte[] b, int off) {
return
((int)(b[off+0]&0xff)) |
((int)(b[off+1]&0xff) << 8) |
((int)(b[off+2]&0xff) << 16) |
((int)(b[off+3]&0xff) << 24);
} private void PUT_32BIT_LSB_FIRST(byte[] b, int off, int value) {
b[off+0] = (byte) (value & 0xff);
b[off+1] = (byte) ((value >> 8) & 0xff);
b[off+2] = (byte) ((value >> 16)& 0xff);
b[off+3] = (byte) ((value >> 24)& 0xff);
} // These are debug routines I was using while trying to
// get this code to generate the same hashes as the C version.
// (IIRC, all the errors were due to the absence of unsigned
// ints in Java.)
/*
private void debugStatus(String m) {
System.out.println(m+":");
System.out.println("in: "+dumpBytes(in));
System.out.println("bits: "+bits);
System.out.println("buf: "
+Integer.toHexString(buf[0])+" "
+Integer.toHexString(buf[1])+" "
+Integer.toHexString(buf[2])+" "
+Integer.toHexString(buf[3]));
}
*/ private static String dumpBytes(byte[] bytes) {
int i;
StringBuffer sb = new StringBuffer();
for (i=0; i<bytes.length; i++) {
if (i%32 == 0 && i!=0) {
sb.append("\n");
}
String s = Integer.toHexString(bytes[i]);
if (s.length() < 2) {
s = "0"+s;
}
if (s.length() > 2) {
s = s.substring(s.length()-2);
}
sb.append(s);
}
return sb.toString();
}
}
// In the C version, a call to MD5STEP is a macro-in-a-macro.
// In this Java version, we pass an Fcore object to represent the
// inner macro, and the MD5STEP() method performs the work of
// the outer macro. It would be good if this could all get
// inlined, but it would take a pretty aggressive compiler to
// inline away the dynamic method lookup made by MD5STEP to
// get to the Fcore.f function. private abstract class Fcore {
abstract int f(int x, int y, int z);
}
private Fcore F1 = new Fcore() {
int f(int x, int y, int z) { return (z ^ (x & (y ^ z))); }};
private Fcore F2 = new Fcore() {
int f(int x, int y, int z) { return (y ^ (z & (x ^ y))); }};
private Fcore F3 = new Fcore() {
int f(int x, int y, int z) { return (x ^ y ^ z); }};
private Fcore F4 = new Fcore() {
int f(int x, int y, int z) { return (y ^ (x | ~z)); }}; private int MD5STEP(Fcore f, int w, int x, int y, int z, int data, int s) {
w += f.f(x, y, z) + data;
w = w<<s | w>>>(32-s);
w += x;
return w;
} private void transform() {
/* load in[] byte array into an internal int array */
int i;
int[] inint = new int[16]; for (i=0; i<16; i++) {
inint[i] = GET_32BIT_LSB_FIRST(in, 4*i);
} int a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3]; a = MD5STEP(F1, a, b, c, d, inint[0] + 0xd76aa478, 7);
d = MD5STEP(F1, d, a, b, c, inint[1] + 0xe8c7b756, 12);
c = MD5STEP(F1, c, d, a, b, inint[2] + 0x242070db, 17);
b = MD5STEP(F1, b, c, d, a, inint[3] + 0xc1bdceee, 22);
a = MD5STEP(F1, a, b, c, d, inint[4] + 0xf57c0faf, 7);
d = MD5STEP(F1, d, a, b, c, inint[5] + 0x4787c62a, 12);
c = MD5STEP(F1, c, d, a, b, inint[6] + 0xa8304613, 17);
b = MD5STEP(F1, b, c, d, a, inint[7] + 0xfd469501, 22);
a = MD5STEP(F1, a, b, c, d, inint[8] + 0x698098d8, 7);
d = MD5STEP(F1, d, a, b, c, inint[9] + 0x8b44f7af, 12);
c = MD5STEP(F1, c, d, a, b, inint[10] + 0xffff5bb1, 17);
b = MD5STEP(F1, b, c, d, a, inint[11] + 0x895cd7be, 22);
a = MD5STEP(F1, a, b, c, d, inint[12] + 0x6b901122, 7);
d = MD5STEP(F1, d, a, b, c, inint[13] + 0xfd987193, 12);
c = MD5STEP(F1, c, d, a, b, inint[14] + 0xa679438e, 17);
b = MD5STEP(F1, b, c, d, a, inint[15] + 0x49b40821, 22);
a = MD5STEP(F2, a, b, c, d, inint[1] + 0xf61e2562, 5);
d = MD5STEP(F2, d, a, b, c, inint[6] + 0xc040b340, 9);
c = MD5STEP(F2, c, d, a, b, inint[11] + 0x265e5a51, 14);
b = MD5STEP(F2, b, c, d, a, inint[0] + 0xe9b6c7aa, 20);
a = MD5STEP(F2, a, b, c, d, inint[5] + 0xd62f105d, 5);
d = MD5STEP(F2, d, a, b, c, inint[10] + 0x02441453, 9);
c = MD5STEP(F2, c, d, a, b, inint[15] + 0xd8a1e681, 14);
b = MD5STEP(F2, b, c, d, a, inint[4] + 0xe7d3fbc8, 20);
a = MD5STEP(F2, a, b, c, d, inint[9] + 0x21e1cde6, 5);
d = MD5STEP(F2, d, a, b, c, inint[14] + 0xc33707d6, 9);
c = MD5STEP(F2, c, d, a, b, inint[3] + 0xf4d50d87, 14);
b = MD5STEP(F2, b, c, d, a, inint[8] + 0x455a14ed, 20);
a = MD5STEP(F2, a, b, c, d, inint[13] + 0xa9e3e905, 5);
d = MD5STEP(F2, d, a, b, c, inint[2] + 0xfcefa3f8, 9);
c = MD5STEP(F2, c, d, a, b, inint[7] + 0x676f02d9, 14);
b = MD5STEP(F2, b, c, d, a, inint[12] + 0x8d2a4c8a, 20);
a = MD5STEP(F3, a, b, c, d, inint[5] + 0xfffa3942, 4);
d = MD5STEP(F3, d, a, b, c, inint[8] + 0x8771f681, 11);
c = MD5STEP(F3, c, d, a, b, inint[11] + 0x6d9d6122, 16);
b = MD5STEP(F3, b, c, d, a, inint[14] + 0xfde5380c, 23);
a = MD5STEP(F3, a, b, c, d, inint[1] + 0xa4beea44, 4);
d = MD5STEP(F3, d, a, b, c, inint[4] + 0x4bdecfa9, 11);
c = MD5STEP(F3, c, d, a, b, inint[7] + 0xf6bb4b60, 16);
b = MD5STEP(F3, b, c, d, a, inint[10] + 0xbebfbc70, 23);
a = MD5STEP(F3, a, b, c, d, inint[13] + 0x289b7ec6, 4);
d = MD5STEP(F3, d, a, b, c, inint[0] + 0xeaa127fa, 11);
c = MD5STEP(F3, c, d, a, b, inint[3] + 0xd4ef3085, 16);
b = MD5STEP(F3, b, c, d, a, inint[6] + 0x04881d05, 23);
a = MD5STEP(F3, a, b, c, d, inint[9] + 0xd9d4d039, 4);
d = MD5STEP(F3, d, a, b, c, inint[12] + 0xe6db99e5, 11);
c = MD5STEP(F3, c, d, a, b, inint[15] + 0x1fa27cf8, 16);
b = MD5STEP(F3, b, c, d, a, inint[2] + 0xc4ac5665, 23);
a = MD5STEP(F4, a, b, c, d, inint[0] + 0xf4292244, 6);
d = MD5STEP(F4, d, a, b, c, inint[7] + 0x432aff97, 10);
c = MD5STEP(F4, c, d, a, b, inint[14] + 0xab9423a7, 15);
b = MD5STEP(F4, b, c, d, a, inint[5] + 0xfc93a039, 21);
a = MD5STEP(F4, a, b, c, d, inint[12] + 0x655b59c3, 6);
d = MD5STEP(F4, d, a, b, c, inint[3] + 0x8f0ccc92, 10);
c = MD5STEP(F4, c, d, a, b, inint[10] + 0xffeff47d, 15);
b = MD5STEP(F4, b, c, d, a, inint[1] + 0x85845dd1, 21);
a = MD5STEP(F4, a, b, c, d, inint[8] + 0x6fa87e4f, 6);
d = MD5STEP(F4, d, a, b, c, inint[15] + 0xfe2ce6e0, 10);
c = MD5STEP(F4, c, d, a, b, inint[6] + 0xa3014314, 15);
b = MD5STEP(F4, b, c, d, a, inint[13] + 0x4e0811a1, 21);
a = MD5STEP(F4, a, b, c, d, inint[4] + 0xf7537e82, 6);
d = MD5STEP(F4, d, a, b, c, inint[11] + 0xbd3af235, 10);
c = MD5STEP(F4, c, d, a, b, inint[2] + 0x2ad7d2bb, 15);
b = MD5STEP(F4, b, c, d, a, inint[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
} private int GET_32BIT_LSB_FIRST(byte[] b, int off) {
return
((int)(b[off+0]&0xff)) |
((int)(b[off+1]&0xff) << 8) |
((int)(b[off+2]&0xff) << 16) |
((int)(b[off+3]&0xff) << 24);
} private void PUT_32BIT_LSB_FIRST(byte[] b, int off, int value) {
b[off+0] = (byte) (value & 0xff);
b[off+1] = (byte) ((value >> 8) & 0xff);
b[off+2] = (byte) ((value >> 16)& 0xff);
b[off+3] = (byte) ((value >> 24)& 0xff);
} // These are debug routines I was using while trying to
// get this code to generate the same hashes as the C version.
// (IIRC, all the errors were due to the absence of unsigned
// ints in Java.)
/*
private void debugStatus(String m) {
System.out.println(m+":");
System.out.println("in: "+dumpBytes(in));
System.out.println("bits: "+bits);
System.out.println("buf: "
+Integer.toHexString(buf[0])+" "
+Integer.toHexString(buf[1])+" "
+Integer.toHexString(buf[2])+" "
+Integer.toHexString(buf[3]));
}
*/ private static String dumpBytes(byte[] bytes) {
int i;
StringBuffer sb = new StringBuffer();
for (i=0; i<bytes.length; i++) {
if (i%32 == 0 && i!=0) {
sb.append("\n");
}
String s = Integer.toHexString(bytes[i]);
if (s.length() < 2) {
s = "0"+s;
}
if (s.length() > 2) {
s = s.substring(s.length()-2);
}
sb.append(s);
}
return sb.toString();
}
}
* 此处插入类型说明。
* 创建日期:(02.3.26 15:12:55)
* @author:Administrator
*/
class MD5 {
private final static int ChainingVariable[]={0x67452301,0xefcdab89,0x98badcfe,0x10325476};
/**
* MD5 构造子注解。
*/
public MD5() {
super();
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:39:19)
* @return String
* @param Data byte[]
*/
private static String bytes2HexString(byte[] Data) {
StringBuffer sb=new StringBuffer("");
char[] id={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
byte d=0;
for(int i=0;i<Data.length;i++){
d=Data[i];
sb.append(id[(d &0x0f0)>>>4]).append(id[d&0x0f]);
}
return sb.toString();
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:39:19)
* @param Digest int[]
* @param Data int[]
*/
private static void calculate(int[] Digest, int[] Data) {
round1(Digest,Data);
round2(Digest,Data);
round3(Digest,Data);
round4(Digest,Data);
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param output byte[]
* @param input int
* @param pos int
*/
private static void decode(byte[] output, int input,int pos) {
//把长整数long处理为字节
/*
long temp;
for(int i=0;i<4;i++){
temp=0xffL;
if (i>0){
temp=temp<<(i*8);
}
temp=input&temp;
if(i>0){
temp=temp>>>(i*8);
}
output[pos+i]=(byte)(temp);
}
*/
output[pos]=(byte)(input&0xff);
output[pos+1]=(byte)((input>> 8)&0xff);
output[pos+2]=(byte)((input>>16)&0xff);
output[pos+3]=(byte)((input>>24)&0xff);
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param input byte[]
* @param pos int
*/
private static int encode(byte[] input, int pos) {
//把字节处理为长整数long
int ret = 0;
ret =
(input[pos] & 0xff)
+ ((input[pos + 1] & 0xff) << 8)
+ ((input[pos + 2] & 0xff) << 16)
+ ((input[pos + 3] & 0xff) << 24);
return ret;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param X int
* @param Y int
* @param Z int
*/
private static int F(int X, int Y,int Z) {
return (X&Y)|((~X)&Z);
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param a int
* @param b int
* @param c int
* @param d int
* @param Mj int
* @param s int
* @param ti int
*/
private static int FF(int a,int b,int c,int d,int Mj,int s,int ti) {
//a=b+((a+F(b,c,d)+Mj+ti)
//return b+((a+F(b,c,d)+Mj+ti)<<s);//a=FF(a,b,c,d,Mj,s,ti)<<s)
int temp=a+F(b,c,d)+Mj+ti;
temp=(temp<<s)|(temp>>>(32-s));
// temp=(temp<<s);
return b+temp;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:39:19)
* @return byte[]
* @param Data byte[]
*/
private static byte[] Fill(byte[] Data) {
int newlen, endblklen, pad;
byte[] ret; endblklen = Data.length % 64;
if (endblklen < 56) {
pad = 64 - endblklen;
} else {
pad = (64 - endblklen) + 64;
}
newlen = Data.length + pad;
ret = new byte[newlen];
for(int i=0;i<Data.length;i++){
ret[i]=Data[i];
}
ret[Data.length]=(byte)0x80;
for (int i = Data.length+1; i < newlen-8; i++) {
ret[i]=0;
}
long datalenbits = Data.length * 8;
for (int i = 0; i < 8; i++) {
ret[newlen - 8 + i] = (byte) (datalenbits & 0xff);
datalenbits >>= 8;
}
return ret;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param X int
* @param Y int
* @param Z int
*/
private static int G(int X, int Y,int Z) {
return (X&Z)|(Y&(~Z));
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param a int
* @param b int
* @param c int
* @param d int
* @param Mj int
* @param s int
* @param ti int
*/
private static int GG(int a,int b,int c,int d,int Mj,int s,int ti) {
//a=b+((a+G(b,c,d)+Mj+ti)<<s)
//return b+((a+G(b,c,d)+Mj+ti)<<s);//a=b+(a+(G(b,c,d)+Mj+ti)<<s)
int temp=a+G(b,c,d)+Mj+ti;
temp=(temp<<s)|(temp>>>(32-s));
// temp=(temp<<s);
return b+temp;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param X int
* @param Y int
* @param Z int
*/
private static int H(int X, int Y,int Z) {
return X^Y^Z;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param a int
* @param b int
* @param c int
* @param d int
* @param Mj int
* @param s int
* @param ti int
*/
private static int HH(int a,int b,int c,int d,int Mj,int s,int ti) {
//a=b+(a+(H(b,c,d)+Mj+ti)<<s)
//return b+((a+H(b,c,d)+Mj+ti)<<s);//a=b+(a+(H(b,c,d)+Mj+ti)<<s)
int temp=a+H(b,c,d)+Mj+ti;
temp=(temp<<s)|(temp>>>(32-s));
// temp=(temp<<s);
return b+temp;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param X int
* @param Y int
* @param Z int
*/
private static int I(int X, int Y,int Z) {
return Y^(X|(~Z));
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:14:21)
* @return int
* @param a int
* @param b int
* @param c int
* @param d int
* @param Mj int
* @param s int
* @param ti int
*/
private static int II(int a,int b,int c,int d,int Mj,int s,int ti) {
//a=b+(a+(I(b,c,d)+Mj+ti)<<s)
//return b+((a+I(b,c,d)+Mj+ti)<<s);//a=b+(a+(I(b,c,d)+Mj+ti)<<s)
int temp=a+I(b,c,d)+Mj+ti;
temp=(temp<<s)|(temp>>>(32-s));
// temp=(temp<<s);
return b+temp;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 16:57:16)
* @param args java.lang.String[]
*/
public static void main(String[] args) {
String test;
System.out.println("test -->");
if ((test=md5("")).equals("d41d8cd98f00b204e9800998ecf8427e")) {
System.out.println("test:");
}
if (md5("a").equals("0cc175b9c0f1b6a831c399e269772661")) {
System.out.println("test:a");
}
if (md5("abc").equals("900150983cd24fb0d6963f7d28e17f72")) {
System.out.println("test:abc");
}
if (md5("message digest").equals("f96b697d7cb7938d525a2f31aaf161d0")) {
System.out.println("test:message digest");
}
if (md5("abcdefghijklmnopqrstuvwxyz").equals("c3fcd3d76192e4007dfb496cca67e13b")) {
System.out.println("test:abcdefghijklmnopqrstuvwxyz");
}
if (md5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").equals("d174ab98d277d9f5a5611c2c9f419d9f")) {
System.out.println("test:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
}
if (md5("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
.equals("57edf4a22be3c955ac49da2e2107b67a")) {
System.out.println("test:12345678901234567890123456789012345678901234567890123456789012345678901234567890");
}
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:39:19)
* @return String
* @param Data byte[]
*/
private static String md5(byte[] Data) {
/*
byte db[]=Data.getBytes();
*/
byte db[];
db=Fill(Data);
int[] digest=new int[4],tempDigest=new int[4],dt=new int[16];
for(int i=0;i<4;i++){
digest[i]=ChainingVariable[i];
}
int cnt=db.length/64;
for(int i=0;i<cnt;i++){
for (int j=0;j<4;j++){
tempDigest[j]=digest[j];
}
for(int j=0;j<16;j++){
dt[j]=encode(db,i*64+j*4);
}
calculate(digest,dt);
for (int j=0;j<4;j++){
digest[j]+=tempDigest[j];
}
}
String Rets="";
///*
byte[] retb=new byte[16];
for(int i=0,j=0;i<16;i+=4,j++ ){
decode(retb,digest[j],i);
}
Rets=bytes2HexString(retb);
//*/
//Rets=Rets+(tohex(digest[0]) + tohex(digest[1]) + tohex(digest[2]) + tohex(digest[3]));
return Rets;
;
}
/**
* 此处插入方法说明。
* 创建日期:(02.3.26 15:39:19)
* @return String
* @param Data String
*/
private static String md5(String Data) {
/*
byte db[]=Data.getBytes();
*/
byte db[]=new byte[Data.length()];
for(int i=0; i < Data.length(); i++) {
db[i] = (byte) (Data.charAt(i) & 0xff);
}
return md5(db);
;
}