• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.crypto.digests;
2 
3 
4 /**
5  * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
6  */
7 public class MD5Digest
8     extends GeneralDigest
9 {
10     private static final int    DIGEST_LENGTH = 16;
11 
12     private int     H1, H2, H3, H4;         // IV's
13 
14     private int[]   X = new int[16];
15     private int     xOff;
16 
17     /**
18      * Standard constructor
19      */
MD5Digest()20     public MD5Digest()
21     {
22         reset();
23     }
24 
25     /**
26      * Copy constructor.  This will copy the state of the provided
27      * message digest.
28      */
MD5Digest(MD5Digest t)29     public MD5Digest(MD5Digest t)
30     {
31         super(t);
32 
33         H1 = t.H1;
34         H2 = t.H2;
35         H3 = t.H3;
36         H4 = t.H4;
37 
38         System.arraycopy(t.X, 0, X, 0, t.X.length);
39         xOff = t.xOff;
40     }
41 
getAlgorithmName()42     public String getAlgorithmName()
43     {
44         return "MD5";
45     }
46 
getDigestSize()47     public int getDigestSize()
48     {
49         return DIGEST_LENGTH;
50     }
51 
processWord( byte[] in, int inOff)52     protected void processWord(
53         byte[]  in,
54         int     inOff)
55     {
56         X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
57             | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
58 
59         if (xOff == 16)
60         {
61             processBlock();
62         }
63     }
64 
processLength( long bitLength)65     protected void processLength(
66         long    bitLength)
67     {
68         if (xOff > 14)
69         {
70             processBlock();
71         }
72 
73         X[14] = (int)(bitLength & 0xffffffff);
74         X[15] = (int)(bitLength >>> 32);
75     }
76 
unpackWord( int word, byte[] out, int outOff)77     private void unpackWord(
78         int     word,
79         byte[]  out,
80         int     outOff)
81     {
82         out[outOff]     = (byte)word;
83         out[outOff + 1] = (byte)(word >>> 8);
84         out[outOff + 2] = (byte)(word >>> 16);
85         out[outOff + 3] = (byte)(word >>> 24);
86     }
87 
doFinal( byte[] out, int outOff)88     public int doFinal(
89         byte[]  out,
90         int     outOff)
91     {
92         finish();
93 
94         unpackWord(H1, out, outOff);
95         unpackWord(H2, out, outOff + 4);
96         unpackWord(H3, out, outOff + 8);
97         unpackWord(H4, out, outOff + 12);
98 
99         reset();
100 
101         return DIGEST_LENGTH;
102     }
103 
104     /**
105      * reset the chaining variables to the IV values.
106      */
reset()107     public void reset()
108     {
109         super.reset();
110 
111         H1 = 0x67452301;
112         H2 = 0xefcdab89;
113         H3 = 0x98badcfe;
114         H4 = 0x10325476;
115 
116         xOff = 0;
117 
118         for (int i = 0; i != X.length; i++)
119         {
120             X[i] = 0;
121         }
122     }
123 
124     //
125     // round 1 left rotates
126     //
127     private static final int S11 = 7;
128     private static final int S12 = 12;
129     private static final int S13 = 17;
130     private static final int S14 = 22;
131 
132     //
133     // round 2 left rotates
134     //
135     private static final int S21 = 5;
136     private static final int S22 = 9;
137     private static final int S23 = 14;
138     private static final int S24 = 20;
139 
140     //
141     // round 3 left rotates
142     //
143     private static final int S31 = 4;
144     private static final int S32 = 11;
145     private static final int S33 = 16;
146     private static final int S34 = 23;
147 
148     //
149     // round 4 left rotates
150     //
151     private static final int S41 = 6;
152     private static final int S42 = 10;
153     private static final int S43 = 15;
154     private static final int S44 = 21;
155 
156     /*
157      * rotate int x left n bits.
158      */
rotateLeft( int x, int n)159     private int rotateLeft(
160         int x,
161         int n)
162     {
163         return (x << n) | (x >>> (32 - n));
164     }
165 
166     /*
167      * F, G, H and I are the basic MD5 functions.
168      */
F( int u, int v, int w)169     private int F(
170         int u,
171         int v,
172         int w)
173     {
174         return (u & v) | (~u & w);
175     }
176 
G( int u, int v, int w)177     private int G(
178         int u,
179         int v,
180         int w)
181     {
182         return (u & w) | (v & ~w);
183     }
184 
H( int u, int v, int w)185     private int H(
186         int u,
187         int v,
188         int w)
189     {
190         return u ^ v ^ w;
191     }
192 
K( int u, int v, int w)193     private int K(
194         int u,
195         int v,
196         int w)
197     {
198         return v ^ (u | ~w);
199     }
200 
processBlock()201     protected void processBlock()
202     {
203         int a = H1;
204         int b = H2;
205         int c = H3;
206         int d = H4;
207 
208         //
209         // Round 1 - F cycle, 16 times.
210         //
211         a = rotateLeft(a + F(b, c, d) + X[ 0] + 0xd76aa478, S11) + b;
212         d = rotateLeft(d + F(a, b, c) + X[ 1] + 0xe8c7b756, S12) + a;
213         c = rotateLeft(c + F(d, a, b) + X[ 2] + 0x242070db, S13) + d;
214         b = rotateLeft(b + F(c, d, a) + X[ 3] + 0xc1bdceee, S14) + c;
215         a = rotateLeft(a + F(b, c, d) + X[ 4] + 0xf57c0faf, S11) + b;
216         d = rotateLeft(d + F(a, b, c) + X[ 5] + 0x4787c62a, S12) + a;
217         c = rotateLeft(c + F(d, a, b) + X[ 6] + 0xa8304613, S13) + d;
218         b = rotateLeft(b + F(c, d, a) + X[ 7] + 0xfd469501, S14) + c;
219         a = rotateLeft(a + F(b, c, d) + X[ 8] + 0x698098d8, S11) + b;
220         d = rotateLeft(d + F(a, b, c) + X[ 9] + 0x8b44f7af, S12) + a;
221         c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
222         b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
223         a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
224         d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
225         c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
226         b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
227 
228         //
229         // Round 2 - G cycle, 16 times.
230         //
231         a = rotateLeft(a + G(b, c, d) + X[ 1] + 0xf61e2562, S21) + b;
232         d = rotateLeft(d + G(a, b, c) + X[ 6] + 0xc040b340, S22) + a;
233         c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
234         b = rotateLeft(b + G(c, d, a) + X[ 0] + 0xe9b6c7aa, S24) + c;
235         a = rotateLeft(a + G(b, c, d) + X[ 5] + 0xd62f105d, S21) + b;
236         d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
237         c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
238         b = rotateLeft(b + G(c, d, a) + X[ 4] + 0xe7d3fbc8, S24) + c;
239         a = rotateLeft(a + G(b, c, d) + X[ 9] + 0x21e1cde6, S21) + b;
240         d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
241         c = rotateLeft(c + G(d, a, b) + X[ 3] + 0xf4d50d87, S23) + d;
242         b = rotateLeft(b + G(c, d, a) + X[ 8] + 0x455a14ed, S24) + c;
243         a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
244         d = rotateLeft(d + G(a, b, c) + X[ 2] + 0xfcefa3f8, S22) + a;
245         c = rotateLeft(c + G(d, a, b) + X[ 7] + 0x676f02d9, S23) + d;
246         b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
247 
248         //
249         // Round 3 - H cycle, 16 times.
250         //
251         a = rotateLeft(a + H(b, c, d) + X[ 5] + 0xfffa3942, S31) + b;
252         d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x8771f681, S32) + a;
253         c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
254         b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
255         a = rotateLeft(a + H(b, c, d) + X[ 1] + 0xa4beea44, S31) + b;
256         d = rotateLeft(d + H(a, b, c) + X[ 4] + 0x4bdecfa9, S32) + a;
257         c = rotateLeft(c + H(d, a, b) + X[ 7] + 0xf6bb4b60, S33) + d;
258         b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
259         a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
260         d = rotateLeft(d + H(a, b, c) + X[ 0] + 0xeaa127fa, S32) + a;
261         c = rotateLeft(c + H(d, a, b) + X[ 3] + 0xd4ef3085, S33) + d;
262         b = rotateLeft(b + H(c, d, a) + X[ 6] + 0x04881d05, S34) + c;
263         a = rotateLeft(a + H(b, c, d) + X[ 9] + 0xd9d4d039, S31) + b;
264         d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
265         c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
266         b = rotateLeft(b + H(c, d, a) + X[ 2] + 0xc4ac5665, S34) + c;
267 
268         //
269         // Round 4 - K cycle, 16 times.
270         //
271         a = rotateLeft(a + K(b, c, d) + X[ 0] + 0xf4292244, S41) + b;
272         d = rotateLeft(d + K(a, b, c) + X[ 7] + 0x432aff97, S42) + a;
273         c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
274         b = rotateLeft(b + K(c, d, a) + X[ 5] + 0xfc93a039, S44) + c;
275         a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
276         d = rotateLeft(d + K(a, b, c) + X[ 3] + 0x8f0ccc92, S42) + a;
277         c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
278         b = rotateLeft(b + K(c, d, a) + X[ 1] + 0x85845dd1, S44) + c;
279         a = rotateLeft(a + K(b, c, d) + X[ 8] + 0x6fa87e4f, S41) + b;
280         d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
281         c = rotateLeft(c + K(d, a, b) + X[ 6] + 0xa3014314, S43) + d;
282         b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
283         a = rotateLeft(a + K(b, c, d) + X[ 4] + 0xf7537e82, S41) + b;
284         d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
285         c = rotateLeft(c + K(d, a, b) + X[ 2] + 0x2ad7d2bb, S43) + d;
286         b = rotateLeft(b + K(c, d, a) + X[ 9] + 0xeb86d391, S44) + c;
287 
288         H1 += a;
289         H2 += b;
290         H3 += c;
291         H4 += d;
292 
293         //
294         // reset the offset and clean out the word buffer.
295         //
296         xOff = 0;
297         for (int i = 0; i != X.length; i++)
298         {
299             X[i] = 0;
300         }
301     }
302 }
303