root/trunk/LogicMail/src/org/logicprobe/LogicMail/util/MD5.java

Revision 90, 21.2 kB (checked in by octorian, 22 months ago)

Code scrub

Line 
1/*-
2 * Copyright (c) 2006, Derek Konigsberg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its
15 *    contributors may be used to endorse or promote products derived
16 *    from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31package org.logicprobe.LogicMail.util;
32
33/**
34 * This file is a modified version of the one covered by the comments below.
35 * The modifications involved changes in the public interface, general formatting,
36 * and size reduction.
37 * While the RIM API includes an MD5Digest class, it requires a digitally signed
38 * binary to be usable.  Since requiring code signing would impose an undesirable
39 * restriction on this project, this alternative implementation is provided.
40 */
41
42/**
43 * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher.
44 * <p>
45 * Originally written by Santeri Paavolainen, Helsinki Finland 1996.<br>
46 * (c) Santeri Paavolainen, Helsinki Finland 1996<br>
47 * Many changes Copyright (c) 2002 - 2005 Timothy W Macinta<br>
48 * <p>
49 * This library is free software; you can redistribute it and/or modify it under
50 * the terms of the GNU Library General Public License as published by the Free
51 * Software Foundation; either version 2.1 of the License, or (at your option)
52 * any later version.
53 * <p>
54 * This library is distributed in the hope that it will be useful, but WITHOUT
55 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
56 * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
57 * details.
58 * <p>
59 * You should have received a copy of the GNU Library General Public License
60 * along with this library; if not, write to the Free Software Foundation, Inc.,
61 * 675 Mass Ave, Cambridge, MA 02139, USA.
62 * <p>
63 * See http://www.twmacinta.com/myjava/fast_md5.php for more information on this
64 * file and the related files.
65 * <p>
66 * This was originally a rather straight re-implementation of the reference
67 * implementation given in RFC1321 by RSA. It passes the MD5 test suite as
68 * defined in RFC1321.
69 * <p>
70 * Many optimizations made by Timothy W Macinta. Reduced time to checksum a test
71 * file in Java alone to roughly half the time taken compared with
72 * java.security.MessageDigest (within an intepretter). Also added an optional
73 * native method to reduce the time even further. See
74 * http://www.twmacinta.com/myjava/fast_md5.php for further information on the
75 * time improvements achieved.
76 * <p>
77 * Some bug fixes also made by Timothy W Macinta.
78 * <p>
79 * Please note: I (Timothy Macinta) have put this code in the com.twmacinta.util
80 * package only because it came without a package. I was not the the original
81 * author of the code, although I did optimize it (substantially) and fix some
82 * bugs.
83 * <p>
84 * This Java class has been derived from the RSA Data Security, Inc. MD5
85 * Message-Digest Algorithm and its reference implementation.
86 * <p>
87 * This class will attempt to use a native method to quickly compute checksums
88 * when the appropriate native library is available. On Linux, this library
89 * should be named "MD5.so" and on Windows it should be named "MD5.dll". The
90 * code will attempt to locate the library in the following locations in the
91 * order given:
92 *
93 * <ol>
94 * <li>The path specified by the system property
95 * "com.twmacinta.util.MD5.NATIVE_LIB_FILE" (be sure to include "MD5.so" or
96 * "MD5.dll" as appropriate at the end of the path).
97 * <li>A platform specific directory beneath the "lib/arch/" directory. On
98 * Linux for x86, this is "lib/arch/linux_x86/". On Windows for x86, this is
99 * "lib/arch/win32_x86/".
100 * <li>Within the "lib/" directory.
101 * <li>Within the current directory.
102 * </ol>
103 *
104 * <p>
105 * If the library is not found, the code will fall back to the default (slower)
106 * Java code.
107 * <p>
108 * As a side effect of having the code search for the native library,
109 * SecurityExceptions might be thrown on JVMs that have a restrictive
110 * SecurityManager. The initialization code attempts to silently discard these
111 * exceptions and continue, but many SecurityManagers will attempt to notify the
112 * user directly of all SecurityExceptions thrown. Consequently, the code has
113 * provisions for skipping the search for the native library. Any of these
114 * provisions may be used to skip the search as long as they are performed
115 * <i>before</i> the first instance of a com.twmacinta.util.MD5 object is
116 * constructed (note that the convenience stream objects will implicitly create
117 * an MD5 object).
118 * <p>
119 * The first option is to set the system property
120 * "com.twmacinta.util.MD5.NO_NATIVE_LIB" to "true" or "1". Unfortunately,
121 * SecurityManagers may also choose to disallow system property setting, so this
122 * won't be of use in all cases.
123 * <p>
124 * The second option is to call com.twmacinta.util.MD5.initNativeLibrary(true)
125 * before any MD5 objects are constructed.
126 *
127 * @author Santeri Paavolainen <sjpaavol@cc.helsinki.fi>
128 * @author Timothy W Macinta (twm@alum.mit.edu) (optimizations and bug fixes)
129 */
130
131public class MD5 {
132    private static class MD5State {
133        /**
134         * 128-bit state
135         */
136        int state[];
137       
138        /**
139         * 64-bit character count
140         */
141        long count;
142       
143        /**
144         * 64-byte buffer (512 bits) for storing to-be-hashed characters
145         */
146        byte buffer[];
147       
148        public MD5State() {
149            buffer = new byte[64];
150            count = 0;
151            state = new int[4];
152           
153            state[0] = 0x67452301;
154            state[1] = 0xefcdab89;
155            state[2] = 0x98badcfe;
156            state[3] = 0x10325476;
157        }
158       
159        /** Create this State as a copy of another state */
160        public MD5State(MD5State from) {
161            this();
162            int i;
163            for (i = 0; i < buffer.length; i++)
164                this.buffer[i] = from.buffer[i];
165            for (i = 0; i < state.length; i++)
166                this.state[i] = from.state[i];
167            this.count = from.count;
168        }
169    };
170   
171    private MD5State state;
172    private MD5State finals;
173   
174    private static final byte padding[] =
175        {(byte)0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
176          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178          0, 0, 0, 0, 0, 0, 0, 0 };
179   
180    /*
181     * len += shift; for (int i = 0; shift < len; i++, shift += 4) { out[i] =
182     * ((int) (buffer[shift] & 0xff)) | (((int) (buffer[shift + 1] & 0xff)) <<
183     * 8) | (((int) (buffer[shift + 2] & 0xff)) << 16) | (((int)
184     * buffer[shift + 3]) << 24); }
185     */
186
187   
188    private final void decode( final byte buffer[], final int shift, final int[] out) {
189        out[0] = (buffer[shift] & 0xff) | ((buffer[shift + 1] & 0xff) << 8)
190        | ((buffer[shift + 2] & 0xff) << 16)
191        | (buffer[shift + 3] << 24);
192        out[1] = (buffer[shift + 4] & 0xff) | ((buffer[shift + 5] & 0xff) << 8)
193        | ((buffer[shift + 6] & 0xff) << 16)
194        | (buffer[shift + 7] << 24);
195        out[2] = (buffer[shift + 8] & 0xff) | ((buffer[shift + 9] & 0xff) << 8)
196        | ((buffer[shift + 10] & 0xff) << 16)
197        | (buffer[shift + 11] << 24);
198        out[3] = (buffer[shift + 12] & 0xff)
199        | ((buffer[shift + 13] & 0xff) << 8)
200        | ((buffer[shift + 14] & 0xff) << 16)
201        | (buffer[shift + 15] << 24);
202        out[4] = (buffer[shift + 16] & 0xff)
203        | ((buffer[shift + 17] & 0xff) << 8)
204        | ((buffer[shift + 18] & 0xff) << 16)
205        | (buffer[shift + 19] << 24);
206        out[5] = (buffer[shift + 20] & 0xff)
207        | ((buffer[shift + 21] & 0xff) << 8)
208        | ((buffer[shift + 22] & 0xff) << 16)
209        | (buffer[shift + 23] << 24);
210        out[6] = (buffer[shift + 24] & 0xff)
211        | ((buffer[shift + 25] & 0xff) << 8)
212        | ((buffer[shift + 26] & 0xff) << 16)
213        | (buffer[shift + 27] << 24);
214        out[7] = (buffer[shift + 28] & 0xff)
215        | ((buffer[shift + 29] & 0xff) << 8)
216        | ((buffer[shift + 30] & 0xff) << 16)
217        | (buffer[shift + 31] << 24);
218        out[8] = (buffer[shift + 32] & 0xff)
219        | ((buffer[shift + 33] & 0xff) << 8)
220        | ((buffer[shift + 34] & 0xff) << 16)
221        | (buffer[shift + 35] << 24);
222        out[9] = (buffer[shift + 36] & 0xff)
223        | ((buffer[shift + 37] & 0xff) << 8)
224        | ((buffer[shift + 38] & 0xff) << 16)
225        | (buffer[shift + 39] << 24);
226        out[10] = (buffer[shift + 40] & 0xff)
227        | ((buffer[shift + 41] & 0xff) << 8)
228        | ((buffer[shift + 42] & 0xff) << 16)
229        | (buffer[shift + 43] << 24);
230        out[11] = (buffer[shift + 44] & 0xff)
231        | ((buffer[shift + 45] & 0xff) << 8)
232        | ((buffer[shift + 46] & 0xff) << 16)
233        | (buffer[shift + 47] << 24);
234        out[12] = (buffer[shift + 48] & 0xff)
235        | ((buffer[shift + 49] & 0xff) << 8)
236        | ((buffer[shift + 50] & 0xff) << 16)
237        | (buffer[shift + 51] << 24);
238        out[13] = (buffer[shift + 52] & 0xff)
239        | ((buffer[shift + 53] & 0xff) << 8)
240        | ((buffer[shift + 54] & 0xff) << 16)
241        | (buffer[shift + 55] << 24);
242        out[14] = (buffer[shift + 56] & 0xff)
243        | ((buffer[shift + 57] & 0xff) << 8)
244        | ((buffer[shift + 58] & 0xff) << 16)
245        | (buffer[shift + 59] << 24);
246        out[15] = (buffer[shift + 60] & 0xff)
247        | ((buffer[shift + 61] & 0xff) << 8)
248        | ((buffer[shift + 62] & 0xff) << 16)
249        | (buffer[shift + 63] << 24);
250    }
251   
252    private final void transform(MD5State state, byte buffer[], int shift, int[] decode_buf) {
253        int a = state.state[0], b = state.state[1], c = state.state[2], d = state.state[3], x[] = decode_buf;
254       
255        decode(buffer, shift, decode_buf);
256       
257        /* Round 1 */
258        a += ((b & c) | (~b & d)) + x[0] + 0xd76aa478; /* 1 */
259        a = ((a << 7) | (a >>> 25)) + b;
260        d += ((a & b) | (~a & c)) + x[1] + 0xe8c7b756; /* 2 */
261        d = ((d << 12) | (d >>> 20)) + a;
262        c += ((d & a) | (~d & b)) + x[2] + 0x242070db; /* 3 */
263        c = ((c << 17) | (c >>> 15)) + d;
264        b += ((c & d) | (~c & a)) + x[3] + 0xc1bdceee; /* 4 */
265        b = ((b << 22) | (b >>> 10)) + c;
266       
267        a += ((b & c) | (~b & d)) + x[4] + 0xf57c0faf; /* 5 */
268        a = ((a << 7) | (a >>> 25)) + b;
269        d += ((a & b) | (~a & c)) + x[5] + 0x4787c62a; /* 6 */
270        d = ((d << 12) | (d >>> 20)) + a;
271        c += ((d & a) | (~d & b)) + x[6] + 0xa8304613; /* 7 */
272        c = ((c << 17) | (c >>> 15)) + d;
273        b += ((c & d) | (~c & a)) + x[7] + 0xfd469501; /* 8 */
274        b = ((b << 22) | (b >>> 10)) + c;
275       
276        a += ((b & c) | (~b & d)) + x[8] + 0x698098d8; /* 9 */
277        a = ((a << 7) | (a >>> 25)) + b;
278        d += ((a & b) | (~a & c)) + x[9] + 0x8b44f7af; /* 10 */
279        d = ((d << 12) | (d >>> 20)) + a;
280        c += ((d & a) | (~d & b)) + x[10] + 0xffff5bb1; /* 11 */
281        c = ((c << 17) | (c >>> 15)) + d;
282        b += ((c & d) | (~c & a)) + x[11] + 0x895cd7be; /* 12 */
283        b = ((b << 22) | (b >>> 10)) + c;
284       
285        a += ((b & c) | (~b & d)) + x[12] + 0x6b901122; /* 13 */
286        a = ((a << 7) | (a >>> 25)) + b;
287        d += ((a & b) | (~a & c)) + x[13] + 0xfd987193; /* 14 */
288        d = ((d << 12) | (d >>> 20)) + a;
289        c += ((d & a) | (~d & b)) + x[14] + 0xa679438e; /* 15 */
290        c = ((c << 17) | (c >>> 15)) + d;
291        b += ((c & d) | (~c & a)) + x[15] + 0x49b40821; /* 16 */
292        b = ((b << 22) | (b >>> 10)) + c;
293       
294        /* Round 2 */
295        a += ((b & d) | (c & ~d)) + x[1] + 0xf61e2562; /* 17 */
296        a = ((a << 5) | (a >>> 27)) + b;
297        d += ((a & c) | (b & ~c)) + x[6] + 0xc040b340; /* 18 */
298        d = ((d << 9) | (d >>> 23)) + a;
299        c += ((d & b) | (a & ~b)) + x[11] + 0x265e5a51; /* 19 */
300        c = ((c << 14) | (c >>> 18)) + d;
301        b += ((c & a) | (d & ~a)) + x[0] + 0xe9b6c7aa; /* 20 */
302        b = ((b << 20) | (b >>> 12)) + c;
303       
304        a += ((b & d) | (c & ~d)) + x[5] + 0xd62f105d; /* 21 */
305        a = ((a << 5) | (a >>> 27)) + b;
306        d += ((a & c) | (b & ~c)) + x[10] + 0x02441453; /* 22 */
307        d = ((d << 9) | (d >>> 23)) + a;
308        c += ((d & b) | (a & ~b)) + x[15] + 0xd8a1e681; /* 23 */
309        c = ((c << 14) | (c >>> 18)) + d;
310        b += ((c & a) | (d & ~a)) + x[4] + 0xe7d3fbc8; /* 24 */
311        b = ((b << 20) | (b >>> 12)) + c;
312       
313        a += ((b & d) | (c & ~d)) + x[9] + 0x21e1cde6; /* 25 */
314        a = ((a << 5) | (a >>> 27)) + b;
315        d += ((a & c) | (b & ~c)) + x[14] + 0xc33707d6; /* 26 */
316        d = ((d << 9) | (d >>> 23)) + a;
317        c += ((d & b) | (a & ~b)) + x[3] + 0xf4d50d87; /* 27 */
318        c = ((c << 14) | (c >>> 18)) + d;
319        b += ((c & a) | (d & ~a)) + x[8] + 0x455a14ed; /* 28 */
320        b = ((b << 20) | (b >>> 12)) + c;
321       
322        a += ((b & d) | (c & ~d)) + x[13] + 0xa9e3e905; /* 29 */
323        a = ((a << 5) | (a >>> 27)) + b;
324        d += ((a & c) | (b & ~c)) + x[2] + 0xfcefa3f8; /* 30 */
325        d = ((d << 9) | (d >>> 23)) + a;
326        c += ((d & b) | (a & ~b)) + x[7] + 0x676f02d9; /* 31 */
327        c = ((c << 14) | (c >>> 18)) + d;
328        b += ((c & a) | (d & ~a)) + x[12] + 0x8d2a4c8a; /* 32 */
329        b = ((b << 20) | (b >>> 12)) + c;
330       
331        /* Round 3 */
332        a += (b ^ c ^ d) + x[5] + 0xfffa3942; /* 33 */
333        a = ((a << 4) | (a >>> 28)) + b;
334        d += (a ^ b ^ c) + x[8] + 0x8771f681; /* 34 */
335        d = ((d << 11) | (d >>> 21)) + a;
336        c += (d ^ a ^ b) + x[11] + 0x6d9d6122; /* 35 */
337        c = ((c << 16) | (c >>> 16)) + d;
338        b += (c ^ d ^ a) + x[14] + 0xfde5380c; /* 36 */
339        b = ((b << 23) | (b >>> 9)) + c;
340       
341        a += (b ^ c ^ d) + x[1] + 0xa4beea44; /* 37 */
342        a = ((a << 4) | (a >>> 28)) + b;
343        d += (a ^ b ^ c) + x[4] + 0x4bdecfa9; /* 38 */
344        d = ((d << 11) | (d >>> 21)) + a;
345        c += (d ^ a ^ b) + x[7] + 0xf6bb4b60; /* 39 */
346        c = ((c << 16) | (c >>> 16)) + d;
347        b += (c ^ d ^ a) + x[10] + 0xbebfbc70; /* 40 */
348        b = ((b << 23) | (b >>> 9)) + c;
349       
350        a += (b ^ c ^ d) + x[13] + 0x289b7ec6; /* 41 */
351        a = ((a << 4) | (a >>> 28)) + b;
352        d += (a ^ b ^ c) + x[0] + 0xeaa127fa; /* 42 */
353        d = ((d << 11) | (d >>> 21)) + a;
354        c += (d ^ a ^ b) + x[3] + 0xd4ef3085; /* 43 */
355        c = ((c << 16) | (c >>> 16)) + d;
356        b += (c ^ d ^ a) + x[6] + 0x04881d05; /* 44 */
357        b = ((b << 23) | (b >>> 9)) + c;
358       
359        a += (b ^ c ^ d) + x[9] + 0xd9d4d039; /* 33 */
360        a = ((a << 4) | (a >>> 28)) + b;
361        d += (a ^ b ^ c) + x[12] + 0xe6db99e5; /* 34 */
362        d = ((d << 11) | (d >>> 21)) + a;
363        c += (d ^ a ^ b) + x[15] + 0x1fa27cf8; /* 35 */
364        c = ((c << 16) | (c >>> 16)) + d;
365        b += (c ^ d ^ a) + x[2] + 0xc4ac5665; /* 36 */
366        b = ((b << 23) | (b >>> 9)) + c;
367       
368        /* Round 4 */
369        a += (c ^ (b | ~d)) + x[0] + 0xf4292244; /* 49 */
370        a = ((a << 6) | (a >>> 26)) + b;
371        d += (b ^ (a | ~c)) + x[7] + 0x432aff97; /* 50 */
372        d = ((d << 10) | (d >>> 22)) + a;
373        c += (a ^ (d | ~b)) + x[14] + 0xab9423a7; /* 51 */
374        c = ((c << 15) | (c >>> 17)) + d;
375        b += (d ^ (c | ~a)) + x[5] + 0xfc93a039; /* 52 */
376        b = ((b << 21) | (b >>> 11)) + c;
377       
378        a += (c ^ (b | ~d)) + x[12] + 0x655b59c3; /* 53 */
379        a = ((a << 6) | (a >>> 26)) + b;
380        d += (b ^ (a | ~c)) + x[3] + 0x8f0ccc92; /* 54 */
381        d =