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 }