/**
* Java Bean for USAGE:MD5 algorithm
*
* FileName:MD5.java
* PackageName:org.ahpo.security
* Author:ahpo Yang
* Createdate:2006-4-24 14:47:11
*/
Package org.ahpo.security;
Import java.lang.reflect.*;
/*******************************************************************************
* The MD5 class implements the MD5 Message-digest algorithm for RSA Data Security, Inc., in RFC1321 submitted to the IETF.
******************************************************************************/
public class MD5 {
/*
* The following s11-s44 are actually a 4*4 matrix, implemented in the original C implementation using #define, which are implemented as static
* Final is to represent read-only, can be shared among multiple instance in the same process space
*/
static final int S11 = 7;
static final int S12 = 12;
static final int S13 = 17;
static final int S14 = 22;
static final int S21 = 5;
static final int S22 = 9;
static final int S23 = 14;
static final int S24 = 20;
static final int S31 = 4;
static final int S32 = 11;
static final int S33 = 16;
static final int S34 = 23;
static final int S41 = 6;
static final int S42 = 10;
static final int S43 = 15;
static final int S44 = 21;
Static final byte[] PADDING = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0};
/*
* The following three members are the 3 core data used in the MD5 calculation and are defined in the original C implementation in the MD5_CTX structure
*
*/
Private long[] state = new LONG[4]; State (ABCD)
Private long[] count = new long[2]; Number of bits, modulo 2^64 (LSB
First
Private byte[] buffer = new BYTE[64]; Input buffer
/*
* DIGESTHEXSTR is the only public member of the MD5, and is the most recent computed result of the 16-in-ASCII representation.
*/
Public String Digesthexstr;
/*
* Digest, is the most recent calculation results of the 2 internal representation, representing the 128bit MD5 value.
*/
Private byte[] Digest = new BYTE[16];
/*
* GETMD5OFSTR is the main public method of class MD5, and the entry parameter is the string you want to MD5 transform
* Return is the result of the transformation, the result is obtained from the public member Digesthexstr.
*/
public string Getmd5ofstr (string inbuf) {
Md5init ();
Md5update (Inbuf.getbytes (), inbuf.length ());
Md5final ();
Digesthexstr = "";
for (int i = 0; i < i++) {
Digesthexstr + + Bytehex (Digest[i]);
}
return digesthexstr;
}
This is the standard constructor for this class of MD5, JavaBean requires a constructor that is public and has no parameters
Public MD5 () {
Md5init ();
Return
}
/* Md5init is an initialization function that initializes the core variable and loads the standard magic number.
private void Md5init () {
Count[0] = 0L;
COUNT[1] = 0L;
/* Load Magic Initialization constants.
State[0] = 0x67452301l;
STATE[1] = 0xefcdab89l;
STATE[2] = 0x98badcfel;
STATE[3] = 0x10325476l;
Return
}
/*
* F, G, H, I are 4 basic MD5 functions, in the original MD5 C implementation, because they are
* Simple bit operations, which can be implemented as macros for efficiency reasons, in Java, we've implemented them as private methods, with names kept in the original C.
*/
Private long F (long x, long y, long Z) {
Return (x & y) | ((~x) & Z);
}
Private long G (long x, long y, long Z) {
Return (X & Z) | (Y & (~z));
}
Private long H (long x, long y, long Z) {
return x ^ y ^ z;
}
Private long I (long x, long y, long Z) {
Return y ^ (x | (~z));
}
/*
* FF,GG,HH and II will call f,g,h,i for a nearly one-step transform FF, GG, HH, and II transformations for
* Rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent
* Recomputation.
*/
Private long FF (long A, long B, long C, long D, long X, long s, long AC) {
A + + F (b, C, D) + x + ac;
A = ((int) a << s) | ((int) a >>> (32-s));
A + b;
return A;
}
Private long GG (long A, long B, long C, long D, long X, long s, long AC) {
A + + G (b, C, D) + x + ac;
A = ((int) a << s) | ((int) a >>> (32-s));
A + b;
return A;
}
Private long HH (long A, long B, long C, long D, long X, long s, long AC) {
A + + H (b, C, D) + x + ac;
A = ((int) a << s) | ((int) a >>> (32-s));
A + b;
return A;
}
Private long II (long A, long B, long C, long D, long X, long s, long AC) {
A + = I (b, C, D) + x + ac;
A = ((int) a << s) | ((int) a >>> (32-s));
A + b;
return A;
}
/*
* Md5update is the MD5 of the main calculation process, INBUF is to transform the byte string, Inputlen is the length, this
* Function called by GETMD5OFSTR, call Md5init before calling, so design it as private
*/
private void Md5update (byte[] inbuf, int inputlen) {
int I, index, Partlen;
byte[] block = new BYTE[64];
index = (int) (Count[0] >>> 3) & 0x3F;
/* Update Number of bits * *
if ((count[0] + = (Inputlen << 3)) < (Inputlen << 3))
count[1]++;
COUNT[1] + + = (inputlen >>> 29);
Partlen = 64-index;
Transform as many times as possible.
if (Inputlen >= partlen) {
md5memcpy (buffer, INBUF, index, 0, Partlen);
Md5transform (buffer);
for (i = Partlen i + < Inputlen i + = 64) {
MD5MEMCPY (block, inbuf, 0, I, 64);
Md5transform (block);
}
index = 0;
} else
i = 0;
/* Buffer remaining input * *
md5memcpy (buffer, INBUF, index, I, inputlen-i);
}
/*
* Md5final Finishing and filling out output results
*/
private void Md5final () {
Byte[] bits = new BYTE[8];
int index, Padlen;
/* Save Number of bits * *
Encode (Bits, count, 8);
* * Pad out to 64 mod.
index = (int) (Count[0] >>> 3) & 0x3f;
Padlen = (Index < 56)? (56-index): (120-index);
Md5update (PADDING, Padlen);
/* Append length (before padding) * *
Md5update (Bits, 8);
/* Store State in Digest * *
Encode (Digest, State, 16);
}
/*
* md5memcpy is an internally used byte array of block copy functions, starting with the input of the inpos of Len length
* Byte copy to the output Outpos position start
*/
private void md5memcpy (byte[] output, byte[] input, int outpos, int inpos,
int len) {
int i;
for (i = 0; i < len; i++)
Output[outpos + i] = Input[inpos + i];
}
/*
* Md5transform is a MD5 core transformation program, with Md5update calls, block is a chunk of raw bytes
*/
private void Md5transform (byte block[]) {
Long a = state[0], B = state[1], c = state[2], d = state[3];
long[] x = new LONG[16];
Decode (x, block, 64);
/* Round 1 * *
A = FF (A, B, C, D, X[0], S11, 0xd76aa478l); /* 1 * *
D = FF (d, a, B, C, x[1], S12, 0xe8c7b756l); /* 2 * *
c = FF (c, D, a, B, x[2], S13, 0X242070DBL); /* 3 * *
b = FF (b, C, D, A, x[3], S14, 0xc1bdceeel); /* 4 * *
A = FF (A, B, C, D, X[4], S11, 0XF57C0FAFL); /* 5 * *
D = FF (d, a, B, C, x[5], S12, 0x4787c62al); /* 6 * *
c = FF (c, D, a, B, x[6], S13, 0xa8304613l); /* 7 * *
b = FF (b, C, D, A, x[7], S14, 0xfd469501l); /* 8 * *
A = FF (A, B, C, D, X[8], S11, 0x698098d8l); /* 9 * *
D = FF (d, a, B, C, x[9], S12, 0X8B44F7AFL); /* 10 * *
c = FF (c, D, a, B, x[10], S13, 0xffff5bb1l); /* 11 * *
b = FF (b, C, D, A, x[11], S14, 0x895cd7bel); /* 12 * *
A = FF (A, B, C, D, X[12], S11, 0x6b901122l); /* 13 * *
D = FF (d, a, B, C, x[13], S12, 0xfd987193l); /* 14 * *
c = FF (c, D, a, B, x[14], S13, 0xa679438el); /* 15 * *
b = FF (b, C, D, A, x[15], S14, 0x49b40821l); /* 16 * *
/* Round 2 * *
A = GG (A, B, C, D, X[1], S21, 0xf61e2562l); /* 17 * *
D = GG (d, a, B, C, x[6], S22, 0xc040b340l); /* 18 * *
c = GG (c, D, a, B, x[11], S23, 0x265e5a51l); /* 19 * *
b = GG (b, C, D, A, x[0], S24, 0xe9b6c7aal); /* 20 * *
A = GG (A, B, C, D, X[5], S21, 0XD62F105DL); /* 21 * *
D = GG (d, a, B, C, x[10], S22, 0x2441453l); /* 22 * *
c = GG (c, D, a, B, x[15], S23, 0xd8a1e681l); /* 23 * *
b = GG (b, C, D, A, x[4], S24, 0xe7d3fbc8l); /* 24 * *
A = GG (A, B, C, D, X[9], S21, 0x21e1cde6l); /* 25 * *
D = GG (d, a, B, C, x[14], S22, 0xc33707d6l); /* 26 * *
c = GG (c, D, a, B, x[3], S23, 0xf4d50d87l); /* 27 * *
b = GG (b, C, D, A, x[8], S24, 0x455a14edl); /* 28 * *
A = GG (A, B, C, D, X[13], S21, 0xa9e3e905l); /* 29 * *
D = GG (d, a, B, C, x[2], S22, 0xfcefa3f8l); /* 30 * *
c = GG (c, D, a, B, x[7], S23, 0x676f02d9l); /* 31 * *
b = GG (b, C, D, A, x[12], S24, 0x8d2a4c8al); /* 32 * *
/* Round 3 * *
A = HH (A, B, C, D, X[5], S31, 0xfffa3942l); /* 33 * *
D = HH (d, a, B, C, x[8], S32, 0x8771f681l); /* 34 * *
c = HH (c, D, a, B, x[11], S33, 0x6d9d6122l); /* 35 * *
b = HH (b, C, D, A, x[14], S34, 0xfde5380cl); /* 36 * *
A = HH (A, B, C, D, X[1], S31, 0xa4beea44l); /* 37 * *
D = HH (d, a, B, C, x[4], S32, 0x4bdecfa9l); /* 38 * *
c = HH (c, D, a, B, x[7], S33, 0xf6bb4b60l); /* 39 * *
b = HH (b, C, D, A, x[10], S34, 0xbebfbc70l); /* 40 * *
A = HH (A, B, C, D, X[13], S31, 0x289b7ec6l); /* 41 * *
D = HH (d, a, B, C, x[0], S32, 0xeaa127fal); /* 42 * *
c = HH (c, D, a, B, x[3], S33, 0xd4ef3085l); /* 43 * *
b = HH (b, C, D, A, x[6], S34, 0x4881d05l); /* 44 * *
A = HH (A, B, C, D, X[9], S31, 0xd9d4d039l); /* 45 * *
D = HH (d, a, B, C, x[12], S32, 0xe6db99e5l); /* 46 * *
c = HH (c, D, a, B, x[15], S33, 0x1fa27cf8l); /* 47 * *
b = HH (b, C, D, A, x[2], S34, 0xc4ac5665l); /* 48 * *
/* Round 4 * *
A = II (A, B, C, D, X[0], S41, 0xf4292244l); /* 49 * *
D = II (d, a, B, C, x[7], S42, 0x432aff97l); /* 50 * *
c = II (c, D, a, B, x[14], S43, 0xab9423a7l); /* 51 * *
b = II (b, C, D, A, x[5], S44, 0xfc93a039l); /* 52 * *
A = II (A, B, C, D, X[12], S41, 0x655b59c3l); /* 53 * *
D = II (d, a, B, C, x[3], S42, 0x8f0ccc92l); /* 54 * *
c = II (c, D, a, B, x[10], S43, 0XFFEFF47DL); /* 55 * *
b = II (b, C, D, A, x[1], S44, 0x85845dd1l); /* 56 * *
A = II (A, B, C, D, X[8], S41, 0X6FA87E4FL); /* 57 * *
D = II (d, a, B, C, x[15], S42, 0xfe2ce6e0l); /* 58 * *
c = II (c, D, a, B, x[6], S43, 0xa3014314l); /* 59 * *
b = II (b, C, D, A, x[13], S44, 0x4e0811a1l); /* 60 * *
A = II (A, B, C, D, X[4], S41, 0xf7537e82l); /* 61 * *
D = II (d, a, B, C, x[11], S42, 0xbd3af235l); /* 62 * *
c = II (c, D, a, B, x[2], S43, 0X2AD7D2BBL); /* 63 * *
b = II (b, C, D, A, x[9], S44, 0xeb86d391l); /* 64 * *
State[0] + = A;
STATE[1] + b;
STATE[2] + = C;
STATE[3] + = D;
}
/*
* Encode the long array into a byte array, because the Java long type is 64bit, only 32bit is removed to accommodate the original C implementation
*/
private void Encode (byte[] output, long[] input, int len) {
int I, J;
for (i = 0, j = 0; j < Len; i++, J + + 4) {
OUTPUT[J] = (byte) (Input[i] & 0xffL);
Output[j + 1] = (byte) ((Input[i] >>> 8) & 0xffL);
Output[j + 2] = (byte) ((Input[i) >>>) & 0xffL);
Output[j + 3] = (byte) ((Input[i] >>>) & 0xffL);
}
}
/*
* Decode the byte array into a long array in order because the long type of Java is 64bit,
* Synthesis of low 32bit, high 32bit Zero, to adapt to the original C implementation of the use
*/
private void Decode (long[] output, byte[] input, int len) {
int I, J;
for (i = 0, j = 0; j < Len; i++, J + + 4)
Output[i] = B2iu (Input[j]) | (B2iu (input[j + 1]) << 8)
| (B2iu (Input[j + 2]) << 16) | (B2iu (Input[j + 3]) << 24);
Return
}
/*
* B2iu is a "raise" program that I wrote about byte according to the principle of not taking the sign, because Java has no unsigned operation
*/
public static long B2iu (byte b) {
Return b < 0? B & 0x7F + 128:b;
}
/*bytehex (), which converts the number of a byte to a 16-binary ASCII representation,
because the byte ToString in Java does not achieve this, we do not have the
in C language sprintf (Outbuf, "%02x", IB)
*/
public static String Bytehex (Byte ib) {
char[] Digit = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ' A ', ' B ', ' C ', ' D ', ' E ',
' F '};
char[] ob = new char[2];
ob[0] = digit[(ib >>> 4) & 0x0f];
ob[1] = Digit[ib & 0x0f];
string s = new String (OB);
return S;
}
}