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