001: package org.bouncycastle.crypto.digests;
002:
003: /**
004: * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
005: */
006: public class MD5Digest extends GeneralDigest {
007: private static final int DIGEST_LENGTH = 16;
008:
009: private int H1, H2, H3, H4; // IV's
010:
011: private int[] X = new int[16];
012: private int xOff;
013:
014: /**
015: * Standard constructor
016: */
017: public MD5Digest() {
018: reset();
019: }
020:
021: /**
022: * Copy constructor. This will copy the state of the provided
023: * message digest.
024: */
025: public MD5Digest(MD5Digest t) {
026: super (t);
027:
028: H1 = t.H1;
029: H2 = t.H2;
030: H3 = t.H3;
031: H4 = t.H4;
032:
033: System.arraycopy(t.X, 0, X, 0, t.X.length);
034: xOff = t.xOff;
035: }
036:
037: public String getAlgorithmName() {
038: return "MD5";
039: }
040:
041: public int getDigestSize() {
042: return DIGEST_LENGTH;
043: }
044:
045: protected void processWord(byte[] in, int inOff) {
046: X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
047: | ((in[inOff + 2] & 0xff) << 16)
048: | ((in[inOff + 3] & 0xff) << 24);
049:
050: if (xOff == 16) {
051: processBlock();
052: }
053: }
054:
055: protected void processLength(long bitLength) {
056: if (xOff > 14) {
057: processBlock();
058: }
059:
060: X[14] = (int) (bitLength & 0xffffffff);
061: X[15] = (int) (bitLength >>> 32);
062: }
063:
064: private void unpackWord(int word, byte[] out, int outOff) {
065: out[outOff] = (byte) word;
066: out[outOff + 1] = (byte) (word >>> 8);
067: out[outOff + 2] = (byte) (word >>> 16);
068: out[outOff + 3] = (byte) (word >>> 24);
069: }
070:
071: public int doFinal(byte[] out, int outOff) {
072: finish();
073:
074: unpackWord(H1, out, outOff);
075: unpackWord(H2, out, outOff + 4);
076: unpackWord(H3, out, outOff + 8);
077: unpackWord(H4, out, outOff + 12);
078:
079: reset();
080:
081: return DIGEST_LENGTH;
082: }
083:
084: /**
085: * reset the chaining variables to the IV values.
086: */
087: public void reset() {
088: super .reset();
089:
090: H1 = 0x67452301;
091: H2 = 0xefcdab89;
092: H3 = 0x98badcfe;
093: H4 = 0x10325476;
094:
095: xOff = 0;
096:
097: for (int i = 0; i != X.length; i++) {
098: X[i] = 0;
099: }
100: }
101:
102: //
103: // round 1 left rotates
104: //
105: private static final int S11 = 7;
106: private static final int S12 = 12;
107: private static final int S13 = 17;
108: private static final int S14 = 22;
109:
110: //
111: // round 2 left rotates
112: //
113: private static final int S21 = 5;
114: private static final int S22 = 9;
115: private static final int S23 = 14;
116: private static final int S24 = 20;
117:
118: //
119: // round 3 left rotates
120: //
121: private static final int S31 = 4;
122: private static final int S32 = 11;
123: private static final int S33 = 16;
124: private static final int S34 = 23;
125:
126: //
127: // round 4 left rotates
128: //
129: private static final int S41 = 6;
130: private static final int S42 = 10;
131: private static final int S43 = 15;
132: private static final int S44 = 21;
133:
134: /*
135: * rotate int x left n bits.
136: */
137: private int rotateLeft(int x, int n) {
138: return (x << n) | (x >>> (32 - n));
139: }
140:
141: /*
142: * F, G, H and I are the basic MD5 functions.
143: */
144: private int F(int u, int v, int w) {
145: return (u & v) | (~u & w);
146: }
147:
148: private int G(int u, int v, int w) {
149: return (u & w) | (v & ~w);
150: }
151:
152: private int H(int u, int v, int w) {
153: return u ^ v ^ w;
154: }
155:
156: private int K(int u, int v, int w) {
157: return v ^ (u | ~w);
158: }
159:
160: protected void processBlock() {
161: int a = H1;
162: int b = H2;
163: int c = H3;
164: int d = H4;
165:
166: //
167: // Round 1 - F cycle, 16 times.
168: //
169: a = rotateLeft(a + F(b, c, d) + X[0] + 0xd76aa478, S11) + b;
170: d = rotateLeft(d + F(a, b, c) + X[1] + 0xe8c7b756, S12) + a;
171: c = rotateLeft(c + F(d, a, b) + X[2] + 0x242070db, S13) + d;
172: b = rotateLeft(b + F(c, d, a) + X[3] + 0xc1bdceee, S14) + c;
173: a = rotateLeft(a + F(b, c, d) + X[4] + 0xf57c0faf, S11) + b;
174: d = rotateLeft(d + F(a, b, c) + X[5] + 0x4787c62a, S12) + a;
175: c = rotateLeft(c + F(d, a, b) + X[6] + 0xa8304613, S13) + d;
176: b = rotateLeft(b + F(c, d, a) + X[7] + 0xfd469501, S14) + c;
177: a = rotateLeft(a + F(b, c, d) + X[8] + 0x698098d8, S11) + b;
178: d = rotateLeft(d + F(a, b, c) + X[9] + 0x8b44f7af, S12) + a;
179: c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
180: b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
181: a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
182: d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
183: c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
184: b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
185:
186: //
187: // Round 2 - G cycle, 16 times.
188: //
189: a = rotateLeft(a + G(b, c, d) + X[1] + 0xf61e2562, S21) + b;
190: d = rotateLeft(d + G(a, b, c) + X[6] + 0xc040b340, S22) + a;
191: c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
192: b = rotateLeft(b + G(c, d, a) + X[0] + 0xe9b6c7aa, S24) + c;
193: a = rotateLeft(a + G(b, c, d) + X[5] + 0xd62f105d, S21) + b;
194: d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
195: c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
196: b = rotateLeft(b + G(c, d, a) + X[4] + 0xe7d3fbc8, S24) + c;
197: a = rotateLeft(a + G(b, c, d) + X[9] + 0x21e1cde6, S21) + b;
198: d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
199: c = rotateLeft(c + G(d, a, b) + X[3] + 0xf4d50d87, S23) + d;
200: b = rotateLeft(b + G(c, d, a) + X[8] + 0x455a14ed, S24) + c;
201: a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
202: d = rotateLeft(d + G(a, b, c) + X[2] + 0xfcefa3f8, S22) + a;
203: c = rotateLeft(c + G(d, a, b) + X[7] + 0x676f02d9, S23) + d;
204: b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
205:
206: //
207: // Round 3 - H cycle, 16 times.
208: //
209: a = rotateLeft(a + H(b, c, d) + X[5] + 0xfffa3942, S31) + b;
210: d = rotateLeft(d + H(a, b, c) + X[8] + 0x8771f681, S32) + a;
211: c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
212: b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
213: a = rotateLeft(a + H(b, c, d) + X[1] + 0xa4beea44, S31) + b;
214: d = rotateLeft(d + H(a, b, c) + X[4] + 0x4bdecfa9, S32) + a;
215: c = rotateLeft(c + H(d, a, b) + X[7] + 0xf6bb4b60, S33) + d;
216: b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
217: a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
218: d = rotateLeft(d + H(a, b, c) + X[0] + 0xeaa127fa, S32) + a;
219: c = rotateLeft(c + H(d, a, b) + X[3] + 0xd4ef3085, S33) + d;
220: b = rotateLeft(b + H(c, d, a) + X[6] + 0x04881d05, S34) + c;
221: a = rotateLeft(a + H(b, c, d) + X[9] + 0xd9d4d039, S31) + b;
222: d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
223: c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
224: b = rotateLeft(b + H(c, d, a) + X[2] + 0xc4ac5665, S34) + c;
225:
226: //
227: // Round 4 - K cycle, 16 times.
228: //
229: a = rotateLeft(a + K(b, c, d) + X[0] + 0xf4292244, S41) + b;
230: d = rotateLeft(d + K(a, b, c) + X[7] + 0x432aff97, S42) + a;
231: c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
232: b = rotateLeft(b + K(c, d, a) + X[5] + 0xfc93a039, S44) + c;
233: a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
234: d = rotateLeft(d + K(a, b, c) + X[3] + 0x8f0ccc92, S42) + a;
235: c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
236: b = rotateLeft(b + K(c, d, a) + X[1] + 0x85845dd1, S44) + c;
237: a = rotateLeft(a + K(b, c, d) + X[8] + 0x6fa87e4f, S41) + b;
238: d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
239: c = rotateLeft(c + K(d, a, b) + X[6] + 0xa3014314, S43) + d;
240: b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
241: a = rotateLeft(a + K(b, c, d) + X[4] + 0xf7537e82, S41) + b;
242: d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
243: c = rotateLeft(c + K(d, a, b) + X[2] + 0x2ad7d2bb, S43) + d;
244: b = rotateLeft(b + K(c, d, a) + X[9] + 0xeb86d391, S44) + c;
245:
246: H1 += a;
247: H2 += b;
248: H3 += c;
249: H4 += d;
250:
251: //
252: // reset the offset and clean out the word buffer.
253: //
254: xOff = 0;
255: for (int i = 0; i != X.length; i++) {
256: X[i] = 0;
257: }
258: }
259: }
|