1 54 55 package com.sslexplorer.unixauth; 56 57 import com.maverick.crypto.digests.MD5Digest; 58 59 60 65 66 99 100 public final class MD5Crypt { 101 102 107 108 static public void main(String argv[]) { 109 if ((argv.length < 1) || (argv.length > 2)) { 110 System.err.println("Usage: MD5Crypt password salt"); 111 System.exit(1); 112 } 113 114 if (argv.length == 2) { 115 System.err.println(MD5Crypt.crypt(argv[0], argv[1])); 116 } else { 117 System.err.println(MD5Crypt.crypt(argv[0])); 118 } 119 120 System.exit(0); 121 } 122 123 static private final String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 124 125 static private final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 126 127 static private final String to64(long v, int size) { 128 StringBuffer result = new StringBuffer (); 129 130 while (--size >= 0) { 131 result.append(itoa64.charAt((int) (v & 0x3f))); 132 v >>>= 6; 133 } 134 135 return result.toString(); 136 } 137 138 static private final void clearbits(byte bits[]) { 139 for (int i = 0; i < bits.length; i++) { 140 bits[i] = 0; 141 } 142 } 143 144 148 149 static private final int bytes2u(byte inp) { 150 return (int) inp & 0xff; 151 } 152 153 169 170 static public final String crypt(String password) { 171 StringBuffer salt = new StringBuffer (); 172 java.util.Random randgen = new java.util.Random (); 173 174 175 176 while (salt.length() < 8) { 177 int index = (int) (randgen.nextFloat() * SALTCHARS.length()); 178 salt.append(SALTCHARS.substring(index, index + 1)); 179 } 180 181 return MD5Crypt.crypt(password, salt.toString()); 182 } 183 184 205 206 static public final String crypt(String password, String salt) { 207 211 212 String magic = "$1$"; 213 byte finalState[]; 214 MD5Digest ctx, ctx1; 215 long l; 216 217 218 219 220 221 222 223 if (salt.startsWith(magic)) { 224 salt = salt.substring(magic.length()); 225 } 226 227 228 229 if (salt.indexOf('$') != -1) { 230 salt = salt.substring(0, salt.indexOf('$')); 231 } 232 233 if (salt.length() > 8) { 234 salt = salt.substring(0, 8); 235 } 236 237 ctx = new MD5Digest(); 238 239 write(ctx, password.getBytes()); write(ctx, magic.getBytes()); write(ctx, salt.getBytes()); 244 245 246 ctx1 = new MD5Digest(); 247 write(ctx1, password.getBytes()); 248 write(ctx1, salt.getBytes()); 249 write(ctx1, password.getBytes()); 250 251 252 finalState = new byte[ctx1.getDigestSize()]; 253 ctx1.doFinal(finalState, 0); 254 255 for (int pl = password.length(); pl > 0; pl -= 16) { 256 for (int i = 0; i < (pl > 16 ? 16 : pl); i++) 257 ctx.update(finalState[i]); 258 } 259 260 265 266 clearbits(finalState); 267 268 269 270 for (int i = password.length(); i != 0; i >>>= 1) { 271 if ((i & 1) != 0) { 272 ctx.update(finalState[0]); 273 } else { 274 ctx.update(password.getBytes()[0]); 275 } 276 } 277 278 finalState = new byte[ctx.getDigestSize()]; 279 ctx.doFinal(finalState, 0); 280 281 288 289 for (int i = 0; i < 1000; i++) { 290 ctx1 = new MD5Digest(); 291 292 if ((i & 1) != 0) { 293 write(ctx1, password.getBytes()); 294 } else { 295 for (int c = 0; c < 16; c++) 296 ctx1.update(finalState[c]); 297 } 298 299 if ((i % 3) != 0) { 300 write(ctx1, salt.getBytes()); 301 } 302 303 if ((i % 7) != 0) { 304 write(ctx1, password.getBytes()); 305 } 306 307 if ((i & 1) != 0) { 308 for (int c = 0; c < 16; c++) 309 ctx1.update(finalState[c]); 310 } else { 311 write(ctx1, password.getBytes()); 312 } 313 314 315 finalState = new byte[ctx.getDigestSize()]; 316 ctx1.doFinal(finalState, 0); 317 } 318 319 320 321 StringBuffer result = new StringBuffer (); 322 323 result.append(magic); 324 result.append(salt); 325 result.append("$"); 326 327 l = (bytes2u(finalState[0]) << 16) | (bytes2u(finalState[6]) << 8) | bytes2u(finalState[12]); 328 result.append(to64(l, 4)); 329 330 l = (bytes2u(finalState[1]) << 16) | (bytes2u(finalState[7]) << 8) | bytes2u(finalState[13]); 331 result.append(to64(l, 4)); 332 333 l = (bytes2u(finalState[2]) << 16) | (bytes2u(finalState[8]) << 8) | bytes2u(finalState[14]); 334 result.append(to64(l, 4)); 335 336 l = (bytes2u(finalState[3]) << 16) | (bytes2u(finalState[9]) << 8) | bytes2u(finalState[15]); 337 result.append(to64(l, 4)); 338 339 l = (bytes2u(finalState[4]) << 16) | (bytes2u(finalState[10]) << 8) | bytes2u(finalState[5]); 340 result.append(to64(l, 4)); 341 342 l = bytes2u(finalState[11]); 343 result.append(to64(l, 2)); 344 345 346 clearbits(finalState); 347 348 return result.toString(); 349 } 350 351 static void write(MD5Digest digest, byte[] arr) { 352 digest.update(arr, 0, arr.length); 353 } 354 } | Popular Tags |