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