001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: ///////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp.crypto;
022:
023: public final class MD5 extends BlockMessageDigest implements Cloneable {
024: private static final int HASH_LENGTH = 16;
025: private static final int DATA_LENGTH = 64;
026:
027: private int[] m_data;
028: private int[] m_digest;
029: private byte[] m_temp;
030:
031: private static void byte2int(byte[] src, int srcOffset, int[] dst,
032: int dstOffset, int length) {
033: while (length-- > 0) {
034: dst[dstOffset++] = (src[srcOffset++] & 0xFF)
035: | ((src[srcOffset++] & 0xFF) << 8)
036: | ((src[srcOffset++] & 0xFF) << 16)
037: | ((src[srcOffset++] & 0xFF) << 24);
038: }
039: }
040:
041: protected static int F(int x, int y, int z) {
042: return (z ^ (x & (y ^ z)));
043: }
044:
045: protected static int G(int x, int y, int z) {
046: return (y ^ (z & (x ^ y)));
047: }
048:
049: protected static int H(int x, int y, int z) {
050: return (x ^ y ^ z);
051: }
052:
053: protected static int I(int x, int y, int z) {
054: return (y ^ (x | ~z));
055: }
056:
057: protected static int FF(int a, int b, int c, int d, int k, int s,
058: int t) {
059: a += k + t + F(b, c, d);
060: a = (a << s | a >>> -s);
061: return a + b;
062: }
063:
064: protected static int GG(int a, int b, int c, int d, int k, int s,
065: int t) {
066: a += k + t + G(b, c, d);
067: a = (a << s | a >>> -s);
068: return a + b;
069: }
070:
071: protected static int HH(int a, int b, int c, int d, int k, int s,
072: int t) {
073: a += k + t + H(b, c, d);
074: a = (a << s | a >>> -s);
075: return a + b;
076: }
077:
078: protected static int II(int a, int b, int c, int d, int k, int s,
079: int t) {
080: a += k + t + I(b, c, d);
081: a = (a << s | a >>> -s);
082: return a + b;
083: }
084:
085: public MD5() {
086: super ("MD5");
087: java_init();
088: engineReset();
089: }
090:
091: private void java_init() {
092: m_digest = new int[HASH_LENGTH / 4];
093: m_data = new int[DATA_LENGTH / 4];
094: m_temp = new byte[DATA_LENGTH];
095: }
096:
097: private MD5(MD5 md) {
098: this ();
099: m_data = (int[]) md.m_data.clone();
100: m_digest = (int[]) md.m_digest.clone();
101: m_temp = (byte[]) md.m_temp.clone();
102: }
103:
104: private void java_reset() {
105: m_digest[0] = 0x67452301;
106: m_digest[1] = 0xEFCDAB89;
107: m_digest[2] = 0x98BADCFE;
108: m_digest[3] = 0x10325476;
109: }
110:
111: private void java_transform(byte[] in) {
112: byte2int(in, 0, m_data, 0, DATA_LENGTH / 4);
113: transform(m_data);
114: }
115:
116: protected int engineGetDigestLength() {
117: return HASH_LENGTH;
118: }
119:
120: protected int engineGetDataLength() {
121: return DATA_LENGTH;
122: }
123:
124: protected void engineTransform(byte[] in) {
125: java_transform(in);
126: }
127:
128: protected void transform(int M[]) {
129: int a, b, c, d;
130:
131: a = m_digest[0];
132: b = m_digest[1];
133: c = m_digest[2];
134: d = m_digest[3];
135:
136: a = FF(a, b, c, d, M[0], 7, 0xd76aa478);
137: d = FF(d, a, b, c, M[1], 12, 0xe8c7b756);
138: c = FF(c, d, a, b, M[2], 17, 0x242070db);
139: b = FF(b, c, d, a, M[3], 22, 0xc1bdceee);
140: a = FF(a, b, c, d, M[4], 7, 0xf57c0faf);
141: d = FF(d, a, b, c, M[5], 12, 0x4787c62a);
142: c = FF(c, d, a, b, M[6], 17, 0xa8304613);
143: b = FF(b, c, d, a, M[7], 22, 0xfd469501);
144: a = FF(a, b, c, d, M[8], 7, 0x698098d8);
145: d = FF(d, a, b, c, M[9], 12, 0x8b44f7af);
146: c = FF(c, d, a, b, M[10], 17, 0xffff5bb1);
147: b = FF(b, c, d, a, M[11], 22, 0x895cd7be);
148: a = FF(a, b, c, d, M[12], 7, 0x6b901122);
149: d = FF(d, a, b, c, M[13], 12, 0xfd987193);
150: c = FF(c, d, a, b, M[14], 17, 0xa679438e);
151: b = FF(b, c, d, a, M[15], 22, 0x49b40821);
152:
153: a = GG(a, b, c, d, M[1], 5, 0xf61e2562);
154: d = GG(d, a, b, c, M[6], 9, 0xc040b340);
155: c = GG(c, d, a, b, M[11], 14, 0x265e5a51);
156: b = GG(b, c, d, a, M[0], 20, 0xe9b6c7aa);
157: a = GG(a, b, c, d, M[5], 5, 0xd62f105d);
158: d = GG(d, a, b, c, M[10], 9, 0x02441453);
159: c = GG(c, d, a, b, M[15], 14, 0xd8a1e681);
160: b = GG(b, c, d, a, M[4], 20, 0xe7d3fbc8);
161: a = GG(a, b, c, d, M[9], 5, 0x21e1cde6);
162: d = GG(d, a, b, c, M[14], 9, 0xc33707d6);
163: c = GG(c, d, a, b, M[3], 14, 0xf4d50d87);
164: b = GG(b, c, d, a, M[8], 20, 0x455a14ed);
165: a = GG(a, b, c, d, M[13], 5, 0xa9e3e905);
166: d = GG(d, a, b, c, M[2], 9, 0xfcefa3f8);
167: c = GG(c, d, a, b, M[7], 14, 0x676f02d9);
168: b = GG(b, c, d, a, M[12], 20, 0x8d2a4c8a);
169:
170: a = HH(a, b, c, d, M[5], 4, 0xfffa3942);
171: d = HH(d, a, b, c, M[8], 11, 0x8771f681);
172: c = HH(c, d, a, b, M[11], 16, 0x6d9d6122);
173: b = HH(b, c, d, a, M[14], 23, 0xfde5380c);
174: a = HH(a, b, c, d, M[1], 4, 0xa4beea44);
175: d = HH(d, a, b, c, M[4], 11, 0x4bdecfa9);
176: c = HH(c, d, a, b, M[7], 16, 0xf6bb4b60);
177: b = HH(b, c, d, a, M[10], 23, 0xbebfbc70);
178: a = HH(a, b, c, d, M[13], 4, 0x289b7ec6);
179: d = HH(d, a, b, c, M[0], 11, 0xeaa127fa);
180: c = HH(c, d, a, b, M[3], 16, 0xd4ef3085);
181: b = HH(b, c, d, a, M[6], 23, 0x04881d05);
182: a = HH(a, b, c, d, M[9], 4, 0xd9d4d039);
183: d = HH(d, a, b, c, M[12], 11, 0xe6db99e5);
184: c = HH(c, d, a, b, M[15], 16, 0x1fa27cf8);
185: b = HH(b, c, d, a, M[2], 23, 0xc4ac5665);
186:
187: a = II(a, b, c, d, M[0], 6, 0xf4292244);
188: d = II(d, a, b, c, M[7], 10, 0x432aff97);
189: c = II(c, d, a, b, M[14], 15, 0xab9423a7);
190: b = II(b, c, d, a, M[5], 21, 0xfc93a039);
191: a = II(a, b, c, d, M[12], 6, 0x655b59c3);
192: d = II(d, a, b, c, M[3], 10, 0x8f0ccc92);
193: c = II(c, d, a, b, M[10], 15, 0xffeff47d);
194: b = II(b, c, d, a, M[1], 21, 0x85845dd1);
195: a = II(a, b, c, d, M[8], 6, 0x6fa87e4f);
196: d = II(d, a, b, c, M[15], 10, 0xfe2ce6e0);
197: c = II(c, d, a, b, M[6], 15, 0xa3014314);
198: b = II(b, c, d, a, M[13], 21, 0x4e0811a1);
199: a = II(a, b, c, d, M[4], 6, 0xf7537e82);
200: d = II(d, a, b, c, M[11], 10, 0xbd3af235);
201: c = II(c, d, a, b, M[2], 15, 0x2ad7d2bb);
202: b = II(b, c, d, a, M[9], 21, 0xeb86d391);
203:
204: m_digest[0] += a;
205: m_digest[1] += b;
206: m_digest[2] += c;
207: m_digest[3] += d;
208: }
209:
210: public void engineReset() {
211: super .engineReset();
212: java_reset();
213: }
214:
215: public byte[] engineDigest(byte[] in, int length) {
216: byte b[] = java_digest(in, length);
217: engineReset();
218: return b;
219: }
220:
221: private byte[] java_digest(byte[] in, int pos) {
222: if (pos != 0)
223: System.arraycopy(in, 0, m_temp, 0, pos);
224:
225: m_temp[pos++] = -128; // (byte)0x80;
226:
227: if (pos > DATA_LENGTH - 8) {
228: while (pos < DATA_LENGTH) {
229: m_temp[pos++] = 0;
230: }
231:
232: byte2int(m_temp, 0, m_data, 0, DATA_LENGTH / 4);
233: transform(m_data);
234: pos = 0;
235: }
236:
237: while (pos < DATA_LENGTH - 8) {
238: m_temp[pos++] = 0;
239: }
240:
241: byte2int(m_temp, 0, m_data, 0, (DATA_LENGTH / 4) - 2);
242:
243: int bc = bitcount();
244: m_data[14] = bc;
245: m_data[15] = 0;
246:
247: transform(m_data);
248:
249: byte buf[] = new byte[HASH_LENGTH];
250:
251: int off = 0;
252: for (int i = 0; i < HASH_LENGTH / 4; ++i) {
253: int d = m_digest[i];
254: buf[off++] = (byte) d;
255: buf[off++] = (byte) (d >>> 8);
256: buf[off++] = (byte) (d >>> 16);
257: buf[off++] = (byte) (d >>> 24);
258: }
259:
260: return buf;
261: }
262:
263: public Object clone() {
264: return new MD5(this);
265: }
266: }
|