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 }