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 }