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