1 /**
2 * Copyright 2005-2006 the original author or authors.
3 *
4 * Licensed under the Gnu General Pubic License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/gpl-license.php
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the Gnu General Public License for more details.
14 */
15 package org.figure8.join.util;
16
17 /**
18 * Unix Crypt. Implements the one way cryptography used by Unix systems for
19 * simple password protection. This class has been extracted from
20 * <a href="http://jetty.mortbay.org">Jetty</a> package.<br/>
21 *
22 * Copyright (c) 1996 Aki Yoshida. All rights reserved.<br/>
23 *
24 * Permission to use, copy, modify and distribute this software for
25 * non-commercial or commercial purposes and without fee is hereby granted
26 * provided that this copyright notice appears in all copies.
27 *
28 * @version 0.9, 11/25/96 - $Revision: 1.3 $
29 * @author Aki Yoshida
30 *
31 * modified April 2001
32 * by Iris Van den Broeke, Daniel Deville
33 */
34 public class UnixCrypt{
35
36
37
38
39 private static final byte[] IP = {
40 58, 50, 42, 34, 26, 18, 10, 2,
41 60, 52, 44, 36, 28, 20, 12, 4,
42 62, 54, 46, 38, 30, 22, 14, 6,
43 64, 56, 48, 40, 32, 24, 16, 8,
44 57, 49, 41, 33, 25, 17, 9, 1,
45 59, 51, 43, 35, 27, 19, 11, 3,
46 61, 53, 45, 37, 29, 21, 13, 5,
47 63, 55, 47, 39, 31, 23, 15, 7};
48
49
50 private static final byte[] ExpandTr = {
51 32, 1, 2, 3, 4, 5,
52 4, 5, 6, 7, 8, 9,
53 8, 9, 10, 11, 12, 13,
54 12, 13, 14, 15, 16, 17,
55 16, 17, 18, 19, 20, 21,
56 20, 21, 22, 23, 24, 25,
57 24, 25, 26, 27, 28, 29,
58 28, 29, 30, 31, 32, 1};
59
60 private static final byte[] PC1 = {
61 57, 49, 41, 33, 25, 17, 9,
62 1, 58, 50, 42, 34, 26, 18,
63 10, 2, 59, 51, 43, 35, 27,
64 19, 11, 3, 60, 52, 44, 36,
65 63, 55, 47, 39, 31, 23, 15,
66 7, 62, 54, 46, 38, 30, 22,
67 14, 6, 61, 53, 45, 37, 29,
68 21, 13, 5, 28, 20, 12, 4};
69
70
71 private static final byte[] Rotates = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
72
73 private static final byte[] PC2 = {
74 9, 18, 14, 17, 11, 24, 1, 5,
75 22, 25, 3, 28, 15, 6, 21, 10,
76 35, 38, 23, 19, 12, 4, 26, 8,
77 43, 54, 16, 7, 27, 20, 13, 2,
78 0, 0, 41, 52, 31, 37, 47, 55,
79 0, 0, 30, 40, 51, 45, 33, 48,
80 0, 0, 44, 49, 39, 56, 34, 53,
81 0, 0, 46, 42, 50, 36, 29, 32};
82
83 private static final byte[][] S = {
84
85 {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
86 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
87 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
88 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},
89
90 {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
91 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
92 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
93 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},
94
95 {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
96 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
97 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
98 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},
99
100 {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
101 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
102 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
103 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},
104
105 {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
106 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
107 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
108 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},
109
110 {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
111 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
112 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
113 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},
114
115 {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
116 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
117 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
118 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},
119
120 {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
121 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
122 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
123 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}};
124
125 private static final byte[] P32Tr = {
126 16, 7, 20, 21,
127 29, 12, 28, 17,
128 1, 15, 23, 26,
129 5, 18, 31, 10,
130 2, 8, 24, 14,
131 32, 27, 3, 9,
132 19, 13, 30, 6,
133 22, 11, 4, 25};
134
135 private static final byte[] CIFP = {
136 1, 2, 3, 4, 17, 18, 19, 20,
137 5, 6, 7, 8, 21, 22, 23, 24,
138 9, 10, 11, 12, 25, 26, 27, 28,
139 13, 14, 15, 16, 29, 30, 31, 32,
140 33, 34, 35, 36, 49, 50, 51, 52,
141 37, 38, 39, 40, 53, 54, 55, 56,
142 41, 42, 43, 44, 57, 58, 59, 60,
143 45, 46, 47, 48, 61, 62, 63, 64};
144
145 private static final byte[] ITOA64 = {
146 (byte)'.', (byte)'/', (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
147 (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D',
148 (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L',
149 (byte)'M', (byte)'N', (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T',
150 (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b',
151 (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j',
152 (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p', (byte)'q', (byte)'r',
153 (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z'};
154
155
156
157
158 private static byte[] A64TOI = new byte[128];
159
160
161 private static long[][] PC1ROT = new long[16][16];
162
163
164 private static long[][][] PC2ROT = new long[2][16][16];
165
166
167 private static long[][] IE3264 = new long[8][16];
168
169
170 private static long[][] SPE = new long[8][64];
171
172
173 private static long[][] CF6464 = new long[16][16];
174
175
176
177 static {
178 byte[] perm = new byte[64];
179 byte[] temp = new byte[64];
180
181
182 for (int i=0; i<64; i++) A64TOI[ITOA64[i]] = (byte)i;
183
184
185 for (int i=0; i<64; i++) perm[i] = (byte)0;;
186 for (int i=0; i<64; i++) {
187 int k;
188 if ((k = (int)PC2[i]) == 0) continue;
189 k += Rotates[0]-1;
190 if ((k%28) < Rotates[0]) k -= 28;
191 k = (int)PC1[k];
192 if (k > 0) {
193 k--;
194 k = (k|0x07) - (k&0x07);
195 k++;
196 }
197 perm[i] = (byte)k;
198 }
199 init_perm(PC1ROT, perm, 8, 8);
200
201
202 for (int j=0; j<2; j++) {
203 int k;
204 for (int i=0; i<64; i++) perm[i] = temp[i] = 0;
205 for (int i=0; i<64; i++) {
206 if ((k = (int)PC2[i]) == 0) continue;
207 temp[k-1] = (byte)(i+1);
208 }
209 for (int i=0; i<64; i++) {
210 if ((k = (int)PC2[i]) == 0) continue;
211 k += j;
212 if ((k%28) <= j) k -= 28;
213 perm[i] = temp[k];
214 }
215
216 init_perm(PC2ROT[j], perm, 8, 8);
217 }
218
219
220 for (int i=0; i<8; i++) {
221 for (int j=0; j<8; j++) {
222 int k = (j < 2)? 0: IP[ExpandTr[i*6+j-2]-1];
223 if (k > 32) k -= 32;
224 else if (k > 0) k--;
225 if (k > 0) {
226 k--;
227 k = (k|0x07) - (k&0x07);
228 k++;
229 }
230 perm[i*8+j] = (byte)k;
231 }
232 }
233
234 init_perm(IE3264, perm, 4, 8);
235
236
237 for (int i=0; i<64; i++) {
238 int k = IP[CIFP[i]-1];
239 if (k > 0) {
240 k--;
241 k = (k|0x07) - (k&0x07);
242 k++;
243 }
244 perm[k-1] = (byte)(i+1);
245 }
246
247 init_perm(CF6464, perm, 8, 8);
248
249
250 for (int i=0; i<48; i++)
251 perm[i] = P32Tr[ExpandTr[i]-1];
252 for (int t=0; t<8; t++) {
253 for (int j=0; j<64; j++) {
254 int k = (((j >> 0) & 0x01) << 5) | (((j >> 1) & 0x01) << 3) |
255 (((j >> 2) & 0x01) << 2) | (((j >> 3) & 0x01) << 1) |
256 (((j >> 4) & 0x01) << 0) | (((j >> 5) & 0x01) << 4);
257 k = S[t][k];
258 k = (((k >> 3) & 0x01) << 0) | (((k >> 2) & 0x01) << 1) |
259 (((k >> 1) & 0x01) << 2) | (((k >> 0) & 0x01) << 3);
260 for (int i=0; i<32; i++) temp[i] = 0;
261 for (int i=0; i<4; i++) temp[4*t+i] = (byte)((k >> i) & 0x01);
262 long kk = 0;
263 for (int i=24; --i>=0; ) kk = ((kk<<1) |
264 ((long)temp[perm[i]-1])<<32 |
265 ((long)temp[perm[i+24]-1]));
266
267 SPE[t][j] = to_six_bit(kk);
268 }
269 }
270 }
271
272
273
274
275 /**
276 * You can't call the constructer.
277 */
278 private UnixCrypt() { }
279
280
281
282
283 /**
284 * Returns the transposed and split code of a 24-bit code
285 * into a 4-byte code, each having 6 bits.
286 */
287 private static int to_six_bit(int num){
288 return (((num << 26) & 0xfc000000) | ((num << 12) & 0xfc0000) |
289 ((num >> 2) & 0xfc00) | ((num >> 16) & 0xfc));
290 }
291
292 /**
293 * Returns the transposed and split code of two 24-bit code
294 * into two 4-byte code, each having 6 bits.
295 */
296 private static long to_six_bit(long num){
297 return (((num << 26) & 0xfc000000fc000000L) | ((num << 12) & 0xfc000000fc0000L) |
298 ((num >> 2) & 0xfc000000fc00L) | ((num >> 16) & 0xfc000000fcL));
299 }
300
301 /**
302 * Returns the permutation of the given 64-bit code with
303 * the specified permutataion table.
304 */
305 private static long perm6464(long c, long[][]p){
306 long out = 0L;
307 for (int i=8; --i>=0; ) {
308 int t = (int)(0x00ff & c);
309 c >>= 8;
310 long tp = p[i<<1][t&0x0f];
311 out |= tp;
312 tp = p[(i<<1)+1][t>>4];
313 out |= tp;
314 }
315 return out;
316 }
317
318 /**
319 * Returns the permutation of the given 32-bit code with
320 * the specified permutataion table.
321 */
322 private static long perm3264(int c, long[][]p){
323 long out = 0L;
324 for (int i=4; --i>=0; ) {
325 int t = (int)(0x00ff & c);
326 c >>= 8;
327 long tp = p[i<<1][t&0x0f];
328 out |= tp;
329 tp = p[(i<<1)+1][t>>4];
330 out |= tp;
331 }
332 return out;
333 }
334
335 /**
336 * Returns the key schedule for the given key.
337 */
338 private static long[] des_setkey(long keyword){
339 long K = perm6464(keyword, PC1ROT);
340 long[] KS = new long[16];
341 KS[0] = K&~0x0303030300000000L;
342
343 for (int i=1; i<16; i++) {
344 KS[i] = K;
345 K = perm6464(K, PC2ROT[Rotates[i]-1]);
346
347 KS[i] = K&~0x0303030300000000L;
348 }
349 return KS;
350 }
351
352 /**
353 * Returns the DES encrypted code of the given word with the specified
354 * environment.
355 */
356 private static long des_cipher(long in, int salt, int num_iter, long[] KS){
357 salt = to_six_bit(salt);
358 long L = in;
359 long R = L;
360 L &= 0x5555555555555555L;
361 R = (R & 0xaaaaaaaa00000000L) | ((R >> 1) & 0x0000000055555555L);
362 L = ((((L << 1) | (L << 32)) & 0xffffffff00000000L) |
363 ((R | (R >> 32)) & 0x00000000ffffffffL));
364
365 L = perm3264((int)(L>>32), IE3264);
366 R = perm3264((int)(L&0xffffffff), IE3264);
367
368 while (--num_iter >= 0) {
369 for (int loop_count=0; loop_count<8; loop_count++) {
370 long kp;
371 long B;
372 long k;
373
374 kp = KS[(loop_count<<1)];
375 k = ((R>>32) ^ R) & salt & 0xffffffffL;
376 k |= (k<<32);
377 B = (k ^ R ^ kp);
378
379 L ^= (SPE[0][(int)((B>>58)&0x3f)] ^ SPE[1][(int)((B>>50)&0x3f)] ^
380 SPE[2][(int)((B>>42)&0x3f)] ^ SPE[3][(int)((B>>34)&0x3f)] ^
381 SPE[4][(int)((B>>26)&0x3f)] ^ SPE[5][(int)((B>>18)&0x3f)] ^
382 SPE[6][(int)((B>>10)&0x3f)] ^ SPE[7][(int)((B>>2)&0x3f)]);
383
384 kp = KS[(loop_count<<1)+1];
385 k = ((L>>32) ^ L) & salt & 0xffffffffL;
386 k |= (k<<32);
387 B = (k ^ L ^ kp);
388
389 R ^= (SPE[0][(int)((B>>58)&0x3f)] ^ SPE[1][(int)((B>>50)&0x3f)] ^
390 SPE[2][(int)((B>>42)&0x3f)] ^ SPE[3][(int)((B>>34)&0x3f)] ^
391 SPE[4][(int)((B>>26)&0x3f)] ^ SPE[5][(int)((B>>18)&0x3f)] ^
392 SPE[6][(int)((B>>10)&0x3f)] ^ SPE[7][(int)((B>>2)&0x3f)]);
393 }
394
395 L ^= R;
396 R ^= L;
397 L ^= R;
398 }
399 L = ((((L>>35) & 0x0f0f0f0fL) | (((L&0xffffffff)<<1) & 0xf0f0f0f0L))<<32 |
400 (((R>>35) & 0x0f0f0f0fL) | (((R&0xffffffff)<<1) & 0xf0f0f0f0L)));
401
402 L = perm6464(L, CF6464);
403
404 return L;
405 }
406
407 /**
408 * Initializes the given permutation table with the mapping table.
409 */
410 private static void init_perm(long[][] perm, byte[] p, int chars_in, int chars_out){
411 for (int k=0; k<chars_out*8; k++) {
412
413 int l = p[k] - 1;
414 if (l < 0) continue;
415 int i = l>>2;
416 l = 1<<(l&0x03);
417 for (int j=0; j<16; j++) {
418 int s = ((k&0x07)+((7-(k>>3))<<3));
419 if ((j & l) != 0x00) perm[i][j] |= (1L<<s);
420 }
421 }
422 }
423
424
425
426
427 /**
428 * Encrypts String into crypt (Unix) code.
429 * @param key the key to be encrypted
430 * @param setting the salt to be used
431 * @return the encrypted String
432 */
433 public static String crypt(String key, String setting){
434 long constdatablock = 0L;
435 byte[] cryptresult = new byte[13];
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 /**
465 * Convenient method for command line usage.
466 * @param arg Array of arguments (key, value)
467 */
468 public static void main(String[] arg){
469 if (arg.length!=2) {
470 System.err.println("Usage - java c.m.U.UnixCrypt <key> <value>");
471 System.exit(1);
472 }
473
474 System.err.println("Crypt=" + crypt(arg[0], arg[1]));
475 }
476 }