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