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}