001    package railo.commons.digest;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.IOException;
005    import java.io.InputStream;
006    
007    
008    /**
009     * 
010     */
011    public final class MD5  {
012        /**
013         * return md5 from string as string
014         * @param str plain string to get md5 from
015         * @return md5 from string
016         * @throws IOException
017         */
018        public static String getDigestAsString(String str) throws IOException {
019            return  new MD5(str).getDigest();
020         }
021    
022        public static String getDigestAsString(byte[] barr) throws IOException {
023           return  new MD5(barr).getDigest();
024        }
025    
026    
027        public static String getDigestAsString(String str, String defaultValue) {
028            try {
029                            return  new MD5(str).getDigest();
030                    } 
031            catch (Throwable t) {
032                            return defaultValue;
033                    }
034         }
035            
036            public static String stringify(byte digest[]) {
037                    char[] chars = new char[2*digest.length];
038                    int h;
039                    int l;
040                    int count=0;
041                    for (int i = 0 ; i < digest.length; i++) {
042                        h = (digest[i] & 0xf0) >> 4 ;
043                        l = (digest[i] & 0x0f) ;
044                        chars[count++]= ((char)((h>9) ? 'a'+h-10 : '0'+h));
045                        chars[count++]= ((char)((l>9) ? 'a'+l-10 : '0'+l));
046                    }
047                    return new String(chars) ;
048            }
049    
050     private final int F(int x, int y, int z)
051     {
052         return x & y | ~x & z;
053     }
054    
055     private final int G(int x, int y, int z)
056     {
057         return x & z | y & ~z;
058     }
059    
060     private final int H(int x, int y, int z)
061     {
062         return x ^ y ^ z;
063     }
064    
065     private final int I(int x, int y, int z)
066     {
067         return y ^ (x | ~z);
068     }
069    
070     private final int rotate_left(int x, int n)
071     {
072         return x << n | x >>> 32 - n;
073     }
074    
075     private final int FF(int a, int b, int c, int d, int x, int s, int ac)
076     {
077         a += F(b, c, d) + x + ac;
078         a = rotate_left(a, s);
079         a += b;
080         return a;
081     }
082    
083     private final int GG(int a, int b, int c, int d, int x, int s, int ac)
084     {
085         a += G(b, c, d) + x + ac;
086         a = rotate_left(a, s);
087         a += b;
088         return a;
089     }
090    
091     private final int HH(int a, int b, int c, int d, int x, int s, int ac)
092     {
093         a += H(b, c, d) + x + ac;
094         a = rotate_left(a, s);
095         a += b;
096         return a;
097     }
098    
099     private final int II(int a, int b, int c, int d, int x, int s, int ac)
100     {
101         a += I(b, c, d) + x + ac;
102         a = rotate_left(a, s);
103         a += b;
104         return a;
105     }
106    
107     private final void decode(int output[], byte input[], int off, int len)
108     {
109         int i = 0;
110         for(int j = 0; j < len; j += 4)
111         {
112             output[i] = input[off + j] & 0xff | (input[off + j + 1] & 0xff) << 8 | (input[off + j + 2] & 0xff) << 16 | (input[off + j + 3] & 0xff) << 24;
113             i++;
114         }
115    
116     }
117    
118     private final void transform(byte block[], int offset)
119     {
120         int a = state[0];
121         int b = state[1];
122         int c = state[2];
123         int d = state[3];
124         int x[] = new int[16];
125    
126         
127         decode(x, block, offset, 64);
128         a = FF(a, b, c, d, x[0], 7, 0xd76aa478);
129         d = FF(d, a, b, c, x[1], 12, 0xe8c7b756);
130         c = FF(c, d, a, b, x[2], 17, 0x242070db);
131         b = FF(b, c, d, a, x[3], 22, 0xc1bdceee);
132         a = FF(a, b, c, d, x[4], 7, 0xf57c0faf);
133         d = FF(d, a, b, c, x[5], 12, 0x4787c62a);
134         c = FF(c, d, a, b, x[6], 17, 0xa8304613);
135         b = FF(b, c, d, a, x[7], 22, 0xfd469501);
136         a = FF(a, b, c, d, x[8], 7, 0x698098d8);
137         d = FF(d, a, b, c, x[9], 12, 0x8b44f7af);
138         c = FF(c, d, a, b, x[10], 17, -42063);
139         b = FF(b, c, d, a, x[11], 22, 0x895cd7be);
140         a = FF(a, b, c, d, x[12], 7, 0x6b901122);
141         d = FF(d, a, b, c, x[13], 12, 0xfd987193);
142         c = FF(c, d, a, b, x[14], 17, 0xa679438e);
143         b = FF(b, c, d, a, x[15], 22, 0x49b40821);
144         a = GG(a, b, c, d, x[1], 5, 0xf61e2562);
145         d = GG(d, a, b, c, x[6], 9, 0xc040b340);
146         c = GG(c, d, a, b, x[11], 14, 0x265e5a51);
147         b = GG(b, c, d, a, x[0], 20, 0xe9b6c7aa);
148         a = GG(a, b, c, d, x[5], 5, 0xd62f105d);
149         d = GG(d, a, b, c, x[10], 9, 0x2441453);
150         c = GG(c, d, a, b, x[15], 14, 0xd8a1e681);
151         b = GG(b, c, d, a, x[4], 20, 0xe7d3fbc8);
152         a = GG(a, b, c, d, x[9], 5, 0x21e1cde6);
153         d = GG(d, a, b, c, x[14], 9, 0xc33707d6);
154         c = GG(c, d, a, b, x[3], 14, 0xf4d50d87);
155         b = GG(b, c, d, a, x[8], 20, 0x455a14ed);
156         a = GG(a, b, c, d, x[13], 5, 0xa9e3e905);
157         d = GG(d, a, b, c, x[2], 9, 0xfcefa3f8);
158         c = GG(c, d, a, b, x[7], 14, 0x676f02d9);
159         b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
160         a = HH(a, b, c, d, x[5], 4, 0xfffa3942);
161         d = HH(d, a, b, c, x[8], 11, 0x8771f681);
162         c = HH(c, d, a, b, x[11], 16, 0x6d9d6122);
163         b = HH(b, c, d, a, x[14], 23, 0xfde5380c);
164         a = HH(a, b, c, d, x[1], 4, 0xa4beea44);
165         d = HH(d, a, b, c, x[4], 11, 0x4bdecfa9);
166         c = HH(c, d, a, b, x[7], 16, 0xf6bb4b60);
167         b = HH(b, c, d, a, x[10], 23, 0xbebfbc70);
168         a = HH(a, b, c, d, x[13], 4, 0x289b7ec6);
169         d = HH(d, a, b, c, x[0], 11, 0xeaa127fa);
170         c = HH(c, d, a, b, x[3], 16, 0xd4ef3085);
171         b = HH(b, c, d, a, x[6], 23, 0x4881d05);
172         a = HH(a, b, c, d, x[9], 4, 0xd9d4d039);
173         d = HH(d, a, b, c, x[12], 11, 0xe6db99e5);
174         c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
175         b = HH(b, c, d, a, x[2], 23, 0xc4ac5665);
176         a = II(a, b, c, d, x[0], 6, 0xf4292244);
177         d = II(d, a, b, c, x[7], 10, 0x432aff97);
178         c = II(c, d, a, b, x[14], 15, 0xab9423a7);
179         b = II(b, c, d, a, x[5], 21, 0xfc93a039);
180         a = II(a, b, c, d, x[12], 6, 0x655b59c3);
181         d = II(d, a, b, c, x[3], 10, 0x8f0ccc92);
182         c = II(c, d, a, b, x[10], 15, 0xffeff47d);
183         b = II(b, c, d, a, x[1], 21, 0x85845dd1);
184         a = II(a, b, c, d, x[8], 6, 0x6fa87e4f);
185         d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
186         c = II(c, d, a, b, x[6], 15, 0xa3014314);
187         b = II(b, c, d, a, x[13], 21, 0x4e0811a1);
188         a = II(a, b, c, d, x[4], 6, 0xf7537e82);
189         d = II(d, a, b, c, x[11], 10, 0xbd3af235);
190         c = II(c, d, a, b, x[2], 15, 0x2ad7d2bb);
191         b = II(b, c, d, a, x[9], 21, 0xeb86d391);
192         state[0] += a;
193         state[1] += b;
194         state[2] += c;
195         state[3] += d;
196     }
197    
198     private final void update(byte input[], int len)
199     {
200         int index = (int)(count >> 3) & 0x3f;
201         count += len << 3;
202         int partLen = 64 - index;
203         int i = 0;
204         if(len >= partLen)
205         {
206             System.arraycopy(input, 0, buffer, index, partLen);
207             transform(buffer, 0);
208             for(i = partLen; i + 63 < len; i += 64)
209                 transform(input, i);
210    
211             index = 0;
212         } else
213         {
214             i = 0;
215         }
216         System.arraycopy(input, i, buffer, index, len - i);
217     }
218    
219     private byte[] end()
220     {
221         byte bits[] = new byte[8];
222         for(int i = 0; i < 8; i++)
223             bits[i] = (byte)(int)(count >>> i * 8 & 255L);
224    
225         int index = (int)(count >> 3) & 0x3f;
226         int padlen = index >= 56 ? 120 - index : 56 - index;
227         update(padding, padlen);
228         update(bits, 8);
229         return encode(state, 16);
230     }
231    
232     private byte[] encode(int input[], int len)
233     {
234         byte output[] = new byte[len];
235         int i = 0;
236         for(int j = 0; j < len; j += 4)
237         {
238             output[j] = (byte)(input[i] & 0xff);
239             output[j + 1] = (byte)(input[i] >> 8 & 0xff);
240             output[j + 2] = (byte)(input[i] >> 16 & 0xff);
241             output[j + 3] = (byte)(input[i] >> 24 & 0xff);
242             i++;
243         }
244    
245         return output;
246     }
247    
248     /**
249     * @return return the digest
250     * @throws IOException
251     */
252    public String getDigest() throws IOException {
253         byte buffer[] = new byte[1024];
254         int got = -1;
255         if(digest != null)
256             return stringify(digest);
257         while((got = in.read(buffer)) > 0) 
258             update(buffer, got);
259         digest = end();
260        return stringify(digest);
261        
262     }
263    
264    
265    
266     /**
267     * @param input
268     */
269    public MD5(String input) {
270         in = null;
271         //stringp = false;
272         state = null;
273         count = 0L;
274         buffer = null;
275         digest = null;
276         byte bytes[] = new byte[input.length()];
277         input.getBytes(0, bytes.length, bytes, 0);
278         //stringp = true;
279         in = new ByteArrayInputStream(bytes);
280         state = new int[4];
281         buffer = new byte[64];
282         count = 0L;
283         state[0] = 0x67452301;
284         state[1] = 0xefcdab89;
285         state[2] = 0x98badcfe;
286         state[3] = 0x10325476;
287     }
288    
289    public MD5(byte[] bytes) {
290        in = null;
291        //stringp = false;
292        state = null;
293        count = 0L;
294        buffer = null;
295        digest = null;
296        //byte bytes[] = new byte[input.length()];
297        //input.getBytes(0, bytes.length, bytes, 0);
298        //stringp = true;
299        in = new ByteArrayInputStream(bytes);
300        state = new int[4];
301        buffer = new byte[64];
302        count = 0L;
303        state[0] = 0x67452301;
304        state[1] = 0xefcdab89;
305        state[2] = 0x98badcfe;
306        state[3] = 0x10325476;
307    }
308    
309    
310    /*
311     public static final int DIGEST_CHARS = 32;
312     public static final int DIGEST_BYTES = 16;
313     private static final int BUFFER_SIZE = 1024;
314     private static final int S11 = 7;
315     private static final int S12 = 12;
316     private static final int S13 = 17;
317     private static final int S14 = 22;
318     private static final int S21 = 5;
319     private static final int S22 = 9;
320     private static final int S23 = 14;
321     private static final int S24 = 20;
322     private static final int S31 = 4;
323     private static final int S32 = 11;
324     private static final int S33 = 16;
325     private static final int S34 = 23;
326     private static final int S41 = 6;
327     private static final int S42 = 10;
328     private static final int S43 = 15;
329     private static final int S44 = 21;*/
330     private static byte padding[] = {
331         -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
332         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
333         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
334         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
335         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
336         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
337         0, 0, 0, 0
338     };
339     private InputStream in;
340     //private boolean stringp;
341     private int state[];
342     private long count;
343     private byte buffer[];
344     private byte digest[];
345    
346    }