Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/bouncycastle/crypto/digests/MD5Digest.java


1   /*
2   Copyright (c) 2000 The Legion Of The Bouncy Castle
3   (http://www.bouncycastle.org)
4   
5   Permission is hereby granted, free of charge, to any person obtaining
6   a copy of this software and associated documentation files (the "Software"),
7   to deal in the Software without restriction, including without limitation
8   the rights to use, copy, modify, merge, publish, distribute, sublicense,
9   and/or sell copies of the Software, and to permit persons to whom the Software
10  is furnished to do so, subject to the following conditions:
11  
12  The above copyright notice and this permission notice shall be included in all
13  copies or substantial portions of the Software. 
14  
15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
21  THE SOFTWARE. 
22  */
23  package org.bouncycastle.crypto.digests;
24  
25  import org.bouncycastle.crypto.Digest;
26  
27  /**
28   * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
29   */
30  public class MD5Digest
31      extends GeneralDigest
32  {
33      private static final int    DIGEST_LENGTH = 16;
34  
35      private int     H1, H2, H3, H4;         // IV's
36  
37      private int[]   X = new int[16];
38      private int     xOff;
39  
40    /**
41     * Standard constructor
42     */
43      public MD5Digest()
44      {
45          reset();
46      }
47  
48    /**
49     * Copy constructor.  This will copy the state of the provided
50     * message digest.
51     */
52    public MD5Digest(MD5Digest t)
53    {
54      super(t);
55  
56      H1 = t.H1;
57      H2 = t.H2;
58      H3 = t.H3;
59      H4 = t.H4;
60  
61      System.arraycopy(t.X, 0, X, 0, t.X.length);
62      xOff = t.xOff;
63    }
64  
65      public String getAlgorithmName()
66      {
67          return "MD5";
68      }
69  
70      public int getDigestSize()
71      {
72          return DIGEST_LENGTH;
73      }
74  
75      protected void processWord(
76          byte[]  in,
77          int     inOff)
78      {
79          X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
80              | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
81  
82          if (xOff == 16)
83          {
84              processBlock();
85          }
86      }
87  
88      protected void processLength(
89          long    bitLength)
90      {
91          if (xOff > 14)
92          {
93              processBlock();
94          }
95  
96          X[14] = (int)(bitLength & 0xffffffff);
97          X[15] = (int)(bitLength >>> 32);
98      }
99  
100     private void unpackWord(
101         int     word,
102         byte[]  out,
103         int     outOff)
104     {
105         out[outOff]     = (byte)word;
106         out[outOff + 1] = (byte)(word >>> 8);
107         out[outOff + 2] = (byte)(word >>> 16);
108         out[outOff + 3] = (byte)(word >>> 24);
109     }
110 
111     public int doFinal(
112         byte[]  out,
113         int     outOff)
114     {
115         finish();
116 
117         unpackWord(H1, out, outOff);
118         unpackWord(H2, out, outOff + 4);
119         unpackWord(H3, out, outOff + 8);
120         unpackWord(H4, out, outOff + 12);
121 
122         reset();
123 
124         return DIGEST_LENGTH;
125     }
126 
127     /**
128      * reset the chaining variables to the IV values.
129      */
130     public void reset()
131     {
132         super.reset();
133 
134         H1 = 0x67452301;
135         H2 = 0xefcdab89;
136         H3 = 0x98badcfe;
137         H4 = 0x10325476;
138 
139         xOff = 0;
140 
141         for (int i = 0; i != X.length; i++)
142         {
143             X[i] = 0;
144         }
145     }
146 
147     //
148     // round 1 left rotates
149     //
150     private static final int S11 = 7;
151     private static final int S12 = 12;
152     private static final int S13 = 17;
153     private static final int S14 = 22;
154 
155     //
156     // round 2 left rotates
157     //
158     private static final int S21 = 5;
159     private static final int S22 = 9;
160     private static final int S23 = 14;
161     private static final int S24 = 20;
162 
163     //
164     // round 3 left rotates
165     //
166     private static final int S31 = 4;
167     private static final int S32 = 11;
168     private static final int S33 = 16;
169     private static final int S34 = 23;
170 
171     //
172     // round 4 left rotates
173     //
174     private static final int S41 = 6;
175     private static final int S42 = 10;
176     private static final int S43 = 15;
177     private static final int S44 = 21;
178 
179     /*
180      * rotate int x left n bits.
181      */
182     private int rotateLeft(
183         int x,
184         int n)
185     {
186         return (x << n) | (x >>> (32 - n));
187     }
188 
189     /*
190      * F, G, H and I are the basic MD5 functions.
191      */
192     private int F(
193         int u,
194         int v,
195         int w)
196     {
197         return (u & v) | (~u & w);
198     }
199 
200     private int G(
201         int u,
202         int v,
203         int w)
204     {
205         return (u & w) | (v & ~w);
206     }
207 
208     private int H(
209         int u,
210         int v,
211         int w)
212     {
213         return u ^ v ^ w;
214     }
215 
216     private int K(
217         int u,
218         int v,
219         int w)
220     {
221         return v ^ (u | ~w);
222     }
223 
224     protected void processBlock()
225     {
226         int a = H1;
227         int b = H2;
228         int c = H3;
229         int d = H4;
230 
231         //
232         // Round 1 - F cycle, 16 times.
233         //
234         a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
235         d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
236         c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
237         b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
238         a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
239         d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
240         c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
241         b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
242         a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
243         d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
244         c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
245         b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
246         a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
247         d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
248         c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
249         b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
250 
251         //
252         // Round 2 - G cycle, 16 times.
253         //
254         a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
255         d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
256         c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
257         b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
258         a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
259         d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
260         c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
261         b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
262         a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
263         d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
264         c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
265         b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
266         a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
267         d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
268         c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
269         b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
270 
271         //
272         // Round 3 - H cycle, 16 times.
273         //
274         a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
275         d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
276         c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
277         b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
278         a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
279         d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
280         c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
281         b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
282         a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
283         d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
284         c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
285         b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
286         a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
287         d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
288         c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
289         b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
290 
291         //
292         // Round 4 - K cycle, 16 times.
293         //
294         a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
295         d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
296         c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
297         b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
298         a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
299         d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
300         c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
301         b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
302         a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
303         d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
304         c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
305         b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
306         a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
307         d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
308         c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
309         b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
310 
311         H1 += a;
312         H2 += b;
313         H3 += c;
314         H4 += d;
315 
316         //
317         // reset the offset and clean out the word buffer.
318         //
319         xOff = 0;
320         for (int i = 0; i != X.length; i++)
321         {
322             X[i] = 0;
323         }
324     }
325 }