001 /* 002 * @(#)UnixCrypt.java 0.9 96/11/25 003 * 004 * Copyright (c) 1996 Aki Yoshida. All rights reserved. 005 * 006 * Permission to use, copy, modify and distribute this software 007 * for non-commercial or commercial purposes and without fee is 008 * hereby granted provided that this copyright notice appears in 009 * all copies. 010 */ 011 012 package com.hs.mail.security.login; 013 014 /** 015 * Unix crypt(3C) utility 016 * 017 * @version 0.9, 11/25/96 018 * @author Aki Yoshida 019 */ 020 public class CryptPasswordEncoder implements PasswordEncoder { 021 022 /** 023 * (mostly) Standard DES Tables from Tom Truscott 024 */ 025 private static final byte[] IP = { /* initial permutation */ 026 58, 50, 42, 34, 26, 18, 10, 2, 027 60, 52, 44, 36, 28, 20, 12, 4, 028 62, 54, 46, 38, 30, 22, 14, 6, 029 64, 56, 48, 40, 32, 24, 16, 8, 030 57, 49, 41, 33, 25, 17, 9, 1, 031 59, 51, 43, 35, 27, 19, 11, 3, 032 61, 53, 45, 37, 29, 21, 13, 5, 033 63, 55, 47, 39, 31, 23, 15, 7 034 }; 035 036 /** 037 * The final permutation is the inverse of IP - no table is necessary 038 */ 039 private static final byte[] ExpandTr = { /* expansion operation */ 040 32, 1, 2, 3, 4, 5, 041 4, 5, 6, 7, 8, 9, 042 8, 9, 10, 11, 12, 13, 043 12, 13, 14, 15, 16, 17, 044 16, 17, 18, 19, 20, 21, 045 20, 21, 22, 23, 24, 25, 046 24, 25, 26, 27, 28, 29, 047 28, 29, 30, 31, 32, 1 048 }; 049 050 private static final byte[] PC1 = { /* permuted choice table 1 */ 051 57, 49, 41, 33, 25, 17, 9, 052 1, 58, 50, 42, 34, 26, 18, 053 10, 2, 59, 51, 43, 35, 27, 054 19, 11, 3, 60, 52, 44, 36, 055 056 63, 55, 47, 39, 31, 23, 15, 057 7, 62, 54, 46, 38, 30, 22, 058 14, 6, 61, 53, 45, 37, 29, 059 21, 13, 5, 28, 20, 12, 4 060 }; 061 062 private static final byte[] Rotates = { /* PC1 rotation schedule */ 063 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 064 }; 065 066 private static final byte[] PC2 = { /* permuted choice table 2 */ 067 9, 18, 14, 17, 11, 24, 1, 5, 068 22, 25, 3, 28, 15, 6, 21, 10, 069 35, 38, 23, 19, 12, 4, 26, 8, 070 43, 54, 16, 7, 27, 20, 13, 2, 071 072 0, 0, 41, 52, 31, 37, 47, 55, 073 0, 0, 30, 40, 51, 45, 33, 48, 074 0, 0, 44, 49, 39, 56, 34, 53, 075 0, 0, 46, 42, 50, 36, 29, 32 076 }; 077 078 private static final byte[][] S = { /* 48->32 bit substitution tables */ 079 /* S[1] */ 080 {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 081 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 082 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 083 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}, 084 /* S[2] */ 085 {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 086 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 087 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 088 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}, 089 /* S[3] */ 090 {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 091 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 092 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 093 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}, 094 /* S[4] */ 095 { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 096 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 097 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 098 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}, 099 /* S[5] */ 100 { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 101 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 102 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 103 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}, 104 /* S[6] */ 105 {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 106 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 107 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 108 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}, 109 /* S[7] */ 110 { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 111 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 112 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 113 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}, 114 /* S[8] */ 115 {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 116 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 117 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 118 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} 119 }; 120 121 private static final byte[] P32Tr = { /* 32-bit permutation function */ 122 16, 7, 20, 21, 123 29, 12, 28, 17, 124 1, 15, 23, 26, 125 5, 18, 31, 10, 126 2, 8, 24, 14, 127 32, 27, 3, 9, 128 19, 13, 30, 6, 129 22, 11, 4, 25 130 }; 131 132 private static final byte[] CIFP = { /* compressed/interleaved permutation */ 133 1, 2, 3, 4, 17, 18, 19, 20, 134 5, 6, 7, 8, 21, 22, 23, 24, 135 9, 10, 11, 12, 25, 26, 27, 28, 136 13, 14, 15, 16, 29, 30, 31, 32, 137 138 33, 34, 35, 36, 49, 50, 51, 52, 139 37, 38, 39, 40, 53, 54, 55, 56, 140 41, 42, 43, 44, 57, 58, 59, 60, 141 45, 46, 47, 48, 61, 62, 63, 64 142 }; 143 144 private static final byte[] ITOA64 = { /* 0..63 => ascii-64 */ 145 (byte)'.',(byte) '/',(byte) '0',(byte) '1',(byte) '2',(byte) '3',(byte) '4',(byte) '5', 146 (byte)'6',(byte) '7',(byte) '8',(byte) '9',(byte) 'A',(byte) 'B',(byte) 'C',(byte) 'D', 147 (byte)'E',(byte) 'F',(byte) 'G',(byte) 'H',(byte) 'I',(byte) 'J',(byte) 'K',(byte) 'L', 148 (byte)'M',(byte) 'N',(byte) 'O',(byte) 'P',(byte) 'Q',(byte) 'R',(byte) 'S',(byte) 'T', 149 (byte)'U',(byte) 'V',(byte) 'W',(byte) 'X',(byte) 'Y',(byte) 'Z',(byte) 'a',(byte) 'b', 150 (byte)'c',(byte) 'd',(byte) 'e',(byte) 'f',(byte) 'g',(byte) 'h',(byte) 'i',(byte) 'j', 151 (byte)'k',(byte) 'l',(byte) 'm',(byte) 'n',(byte) 'o',(byte) 'p',(byte) 'q',(byte) 'r', 152 (byte)'s',(byte) 't',(byte) 'u',(byte) 'v',(byte) 'w',(byte) 'x',(byte) 'y',(byte) 'z' 153 }; 154 155 /* ===== Tables that are initialized at run time ==================== */ 156 157 /** 158 * ascii-64 => 0..63 159 */ 160 private static byte[] A64TOI = new byte[128]; 161 162 /** 163 * Initial key schedule permutation 164 */ 165 private static long[][] PC1ROT = new long[16][16]; 166 167 /** 168 * Subsequent key schedule rotation permutations 169 */ 170 private static long[][][] PC2ROT = new long[2][16][16]; 171 172 /** 173 * Initial permutation/expansion table 174 */ 175 private static long[][] IE3264 = new long[8][16]; 176 177 /** 178 * Table that combines the S, P, and E operations. 179 */ 180 private static long[][] SPE = new long[8][64]; 181 182 /** 183 * compressed/interleaved => final permutation table 184 */ 185 private static long[][] CF6464 = new long[16][16]; 186 187 static { 188 byte[] perm = new byte[64]; 189 byte[] temp = new byte[64]; 190 191 // inverse table. 192 for (int i=0; i<64; i++) A64TOI[ITOA64[i]] = (byte)i; 193 194 // PC1ROT - bit reverse, then PC1, then Rotate, then PC2 195 for (int i=0; i<64; i++) perm[i] = (byte)0;; 196 for (int i=0; i<64; i++) { 197 int k; 198 if ((k = (int)PC2[i]) == 0) continue; 199 k += Rotates[0]-1; 200 if ((k%28) < Rotates[0]) k -= 28; 201 k = (int)PC1[k]; 202 if (k > 0) { 203 k--; 204 k = (k|0x07) - (k&0x07); 205 k++; 206 } 207 perm[i] = (byte)k; 208 } 209 init_perm(PC1ROT, perm, 8, 8); 210 211 // PC2ROT - PC2 inverse, then Rotate, then PC2 212 for (int j=0; j<2; j++) { 213 int k; 214 for (int i=0; i<64; i++) perm[i] = temp[i] = 0; 215 for (int i=0; i<64; i++) { 216 if ((k = (int)PC2[i]) == 0) continue; 217 temp[k-1] = (byte)(i+1); 218 } 219 for (int i=0; i<64; i++) { 220 if ((k = (int)PC2[i]) == 0) continue; 221 k += j; 222 if ((k%28) <= j) k -= 28; 223 perm[i] = temp[k]; 224 } 225 226 init_perm(PC2ROT[j], perm, 8, 8); 227 } 228 229 // Bit reverse, intial permupation, expantion 230 for (int i=0; i<8; i++) { 231 for (int j=0; j<8; j++) { 232 int k = (j < 2)? 0: IP[ExpandTr[i*6+j-2]-1]; 233 if (k > 32) k -= 32; 234 else if (k > 0) k--; 235 if (k > 0) { 236 k--; 237 k = (k|0x07) - (k&0x07); 238 k++; 239 } 240 perm[i*8+j] = (byte)k; 241 } 242 } 243 244 init_perm(IE3264, perm, 4, 8); 245 246 // Compression, final permutation, bit reverse 247 for (int i=0; i<64; i++) { 248 int k = IP[CIFP[i]-1]; 249 if (k > 0) { 250 k--; 251 k = (k|0x07) - (k&0x07); 252 k++; 253 } 254 perm[k-1] = (byte)(i+1); 255 } 256 257 init_perm(CF6464, perm, 8, 8); 258 259 // SPE table 260 for (int i=0; i<48; i++) 261 perm[i] = P32Tr[ExpandTr[i]-1]; 262 for (int t=0; t<8; t++) { 263 for (int j=0; j<64; j++) { 264 int k = (((j >> 0) & 0x01) << 5) | (((j >> 1) & 0x01) << 3) | 265 (((j >> 2) & 0x01) << 2) | (((j >> 3) & 0x01) << 1) | 266 (((j >> 4) & 0x01) << 0) | (((j >> 5) & 0x01) << 4); 267 k = S[t][k]; 268 k = (((k >> 3) & 0x01) << 0) | (((k >> 2) & 0x01) << 1) | 269 (((k >> 1) & 0x01) << 2) | (((k >> 0) & 0x01) << 3); 270 for (int i=0; i<32; i++) temp[i] = 0; 271 for (int i=0; i<4; i++) temp[4*t+i] = (byte)((k >> i) & 0x01); 272 long kk = 0; 273 for (int i=24; --i>=0; ) kk = ((kk<<1) | 274 ((long)temp[perm[i]-1])<<32 | 275 ((long)temp[perm[i+24]-1])); 276 277 SPE[t][j] = to_six_bit(kk); 278 } 279 } 280 } 281 282 /** 283 * Returns the transposed and split code of a 24-bit code 284 * into a 4-byte code, each having 6 bits. 285 */ 286 private static int to_six_bit(int num) { 287 return (((num << 26) & 0xfc000000) | ((num << 12) & 0xfc0000) | 288 ((num >> 2) & 0xfc00) | ((num >> 16) & 0xfc)); 289 } 290 291 /** 292 * Returns the transposed and split code of two 24-bit code 293 * into two 4-byte code, each having 6 bits. 294 */ 295 private static long to_six_bit(long num) { 296 return (((num << 26) & 0xfc000000fc000000L) | ((num << 12) & 0xfc000000fc0000L) | 297 ((num >> 2) & 0xfc000000fc00L) | ((num >> 16) & 0xfc000000fcL)); 298 } 299 300 /** 301 * Returns the permutation of the given 64-bit code with 302 * the specified permutataion table. 303 */ 304 private static long perm6464(long c, long[][]p) { 305 long out = 0L; 306 for (int i=8; --i>=0; ) { 307 int t = (int)(0x00ff & c); 308 c >>= 8; 309 long tp = p[i<<1][t&0x0f]; 310 out |= tp; 311 tp = p[(i<<1)+1][t>>4]; 312 out |= tp; 313 } 314 return out; 315 } 316 317 /** 318 * Returns the permutation of the given 32-bit code with 319 * the specified permutataion table. 320 */ 321 private static long perm3264(int c, long[][]p) { 322 long out = 0L; 323 for (int i=4; --i>=0; ) { 324 int t = (int)(0x00ff & c); 325 c >>= 8; 326 long tp = p[i<<1][t&0x0f]; 327 out |= tp; 328 tp = p[(i<<1)+1][t>>4]; 329 out |= tp; 330 } 331 return out; 332 } 333 334 /** 335 * Returns the key schedule for the given key. 336 */ 337 private static long[] des_setkey(long keyword) { 338 long K = perm6464(keyword, PC1ROT); 339 long[] KS = new long[16]; 340 KS[0] = K&~0x0303030300000000L; 341 342 for (int i=1; i<16; i++) { 343 KS[i] = K; 344 K = perm6464(K, PC2ROT[Rotates[i]-1]); 345 346 KS[i] = K&~0x0303030300000000L; 347 } 348 return KS; 349 } 350 351 /** 352 * Returns the DES encrypted code of the given word with the specified 353 * environment. 354 */ 355 private static long des_cipher(long in, int salt, int num_iter, long[] KS) { 356 salt = to_six_bit(salt); 357 long L = in; 358 long R = L; 359 L &= 0x5555555555555555L; 360 R = (R & 0xaaaaaaaa00000000L) | ((R >> 1) & 0x0000000055555555L); 361 L = ((((L << 1) | (L << 32)) & 0xffffffff00000000L) | 362 ((R | (R >> 32)) & 0x00000000ffffffffL)); 363 364 L = perm3264((int)(L>>32), IE3264); 365 R = perm3264((int)(L&0xffffffff), IE3264); 366 367 while (--num_iter >= 0) { 368 for (int loop_count=0; loop_count<8; loop_count++) { 369 long kp; 370 long B; 371 long k; 372 373 kp = KS[(loop_count<<1)]; 374 k = ((R>>32) ^ R) & salt & 0xffffffffL; 375 k |= (k<<32); 376 B = (k ^ R ^ kp); 377 378 L ^= (SPE[0][(int)((B>>58)&0x3f)] ^ SPE[1][(int)((B>>50)&0x3f)] ^ 379 SPE[2][(int)((B>>42)&0x3f)] ^ SPE[3][(int)((B>>34)&0x3f)] ^ 380 SPE[4][(int)((B>>26)&0x3f)] ^ SPE[5][(int)((B>>18)&0x3f)] ^ 381 SPE[6][(int)((B>>10)&0x3f)] ^ SPE[7][(int)((B>>2)&0x3f)]); 382 383 kp = KS[(loop_count<<1)+1]; 384 k = ((L>>32) ^ L) & salt & 0xffffffffL; 385 k |= (k<<32); 386 B = (k ^ L ^ kp); 387 388 R ^= (SPE[0][(int)((B>>58)&0x3f)] ^ SPE[1][(int)((B>>50)&0x3f)] ^ 389 SPE[2][(int)((B>>42)&0x3f)] ^ SPE[3][(int)((B>>34)&0x3f)] ^ 390 SPE[4][(int)((B>>26)&0x3f)] ^ SPE[5][(int)((B>>18)&0x3f)] ^ 391 SPE[6][(int)((B>>10)&0x3f)] ^ SPE[7][(int)((B>>2)&0x3f)]); 392 } 393 // swap L and R 394 L ^= R; 395 R ^= L; 396 L ^= R; 397 } 398 L = ((((L>>35) & 0x0f0f0f0fL) | (((L&0xffffffff)<<1) & 0xf0f0f0f0L))<<32 | 399 (((R>>35) & 0x0f0f0f0fL) | (((R&0xffffffff)<<1) & 0xf0f0f0f0L))); 400 401 L = perm6464(L, CF6464); 402 403 return L; 404 } 405 406 /** 407 * Initializes the given permutation table with the mapping table. 408 */ 409 private static void init_perm(long[][] perm, byte[] p, int chars_in, int chars_out) { 410 for (int k=0; k<chars_out*8; k++) { 411 412 int l = p[k] - 1; 413 if (l < 0) continue; 414 int i = l>>2; 415 l = 1<<(l&0x03); 416 for (int j=0; j<16; j++) { 417 int s = ((k&0x07)+((7-(k>>3))<<3)); 418 if ((j & l) != 0x00) perm[i][j] |= (1L<<s); 419 } 420 } 421 } 422 423 /** 424 * Encrypts String into crypt (Unix) code. 425 * 426 * @param key 427 * the key to be encrypted 428 * @param setting 429 * the salt to be used 430 * @return the encrypted String 431 */ 432 @SuppressWarnings("deprecation") 433 public static String crypt(String key, String setting) { 434 long constdatablock = 0L; /* encryption constant */ 435 byte[] cryptresult = new byte[13]; /* encrypted result */ 436 long keyword = 0L; 437 int keylen = key.length(); 438 439 for (int i=0; i<8 ; i++) { 440 keyword = (keyword << 8) | ((i < keylen)? 2*key.charAt(i): 0); 441 } 442 443 long[] KS = des_setkey(keyword); 444 445 int salt = 0; 446 for (int i=2; --i>=0;) { 447 char c = (i < setting.length())? setting.charAt(i): '.'; 448 cryptresult[i] = (byte)c; 449 salt = (salt<<6) | (int)(0x00ff&A64TOI[c]); 450 } 451 452 long rsltblock = des_cipher(constdatablock, salt, 25, KS); 453 454 cryptresult[12] = ITOA64[(((int)rsltblock)<<2)&0x3f]; 455 rsltblock >>= 4; 456 for (int i=12; --i>=2; ) { 457 cryptresult[i] = ITOA64[((int)rsltblock)&0x3f]; 458 rsltblock >>= 6; 459 } 460 461 return new String(cryptresult, 0x00, 0, 13); 462 } 463 464 public CryptPasswordEncoder() { 465 } 466 467 public static String encodePassword(char password[]) { 468 long time = System.currentTimeMillis(); 469 return crypt(String.valueOf(password), Integer.toString( 470 (int) (time & 0xffffffffL), 16)); 471 } 472 473 public String encode(char[] password) { 474 return encodePassword(password); 475 } 476 477 public boolean compare(String encoded, char[] plain) { 478 String salt = encoded.substring(0, 2); 479 return encoded.equals(crypt(String.valueOf(plain), salt)); 480 } 481 482 public static void main(String args[]) { 483 for (int i = 0; i < args.length; i++) { 484 System.out.println(args[i] + ": " 485 + encodePassword(args[i].toCharArray())); 486 } 487 } 488 489 }