Merge branch 'master' of feistymeow.org:feisty_meow
[feisty_meow.git] / kona / src / org / feistymeow / encryption / UnixCrypt.java
1 package org.feistymeow.encryption;\r
2 \r
3 import java.util.ArrayList;\r
4 \r
5 /****************************************************************************\r
6  * Java-based implementation of the unix UnixCrypt(3) command\r
7  *\r
8  * Based upon C source code written by Eric Young, eay@psych.uq.oz.au\r
9  * Java conversion by John F. Dumas, jdumas@zgs.com\r
10  *\r
11  * Found at http://locutus.kingwoodcable.com/jfd/UnixCrypt.html\r
12  * Minor optimizations by Wes Biggs, wes@cacas.org\r
13  *\r
14  * Eric's original code is licensed under the BSD license.  As this is\r
15  * derivative, the same license applies.\r
16  *\r
17  * Note: UnixCrypt.class is much smaller when compiled with javac -O\r
18  ****************************************************************************/\r
19 \r
20 public class UnixCrypt \r
21 {\r
22   private UnixCrypt() {} // defined so class can't be instantiated.\r
23 \r
24   private static final int ITERATIONS = 16;\r
25 \r
26   private static final boolean shifts2[] = {\r
27     false, false, true, true, true, true, true, true,\r
28     false, true,  true, true, true, true, true, false\r
29   };\r
30 \r
31   private static final int skb[][] = {\r
32     {\r
33       /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */\r
34       0x00000000, 0x00000010, 0x20000000, 0x20000010, \r
35       0x00010000, 0x00010010, 0x20010000, 0x20010010, \r
36       0x00000800, 0x00000810, 0x20000800, 0x20000810, \r
37       0x00010800, 0x00010810, 0x20010800, 0x20010810, \r
38       0x00000020, 0x00000030, 0x20000020, 0x20000030, \r
39       0x00010020, 0x00010030, 0x20010020, 0x20010030, \r
40       0x00000820, 0x00000830, 0x20000820, 0x20000830, \r
41       0x00010820, 0x00010830, 0x20010820, 0x20010830, \r
42       0x00080000, 0x00080010, 0x20080000, 0x20080010, \r
43       0x00090000, 0x00090010, 0x20090000, 0x20090010, \r
44       0x00080800, 0x00080810, 0x20080800, 0x20080810, \r
45       0x00090800, 0x00090810, 0x20090800, 0x20090810, \r
46       0x00080020, 0x00080030, 0x20080020, 0x20080030, \r
47       0x00090020, 0x00090030, 0x20090020, 0x20090030, \r
48       0x00080820, 0x00080830, 0x20080820, 0x20080830, \r
49       0x00090820, 0x00090830, 0x20090820, 0x20090830, \r
50     },\r
51     {\r
52       /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */\r
53       0x00000000, 0x02000000, 0x00002000, 0x02002000, \r
54       0x00200000, 0x02200000, 0x00202000, 0x02202000, \r
55       0x00000004, 0x02000004, 0x00002004, 0x02002004, \r
56       0x00200004, 0x02200004, 0x00202004, 0x02202004, \r
57       0x00000400, 0x02000400, 0x00002400, 0x02002400, \r
58       0x00200400, 0x02200400, 0x00202400, 0x02202400, \r
59       0x00000404, 0x02000404, 0x00002404, 0x02002404, \r
60       0x00200404, 0x02200404, 0x00202404, 0x02202404, \r
61       0x10000000, 0x12000000, 0x10002000, 0x12002000, \r
62       0x10200000, 0x12200000, 0x10202000, 0x12202000, \r
63       0x10000004, 0x12000004, 0x10002004, 0x12002004, \r
64       0x10200004, 0x12200004, 0x10202004, 0x12202004, \r
65       0x10000400, 0x12000400, 0x10002400, 0x12002400, \r
66       0x10200400, 0x12200400, 0x10202400, 0x12202400, \r
67       0x10000404, 0x12000404, 0x10002404, 0x12002404, \r
68       0x10200404, 0x12200404, 0x10202404, 0x12202404, \r
69     },\r
70     {\r
71       /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */\r
72       0x00000000, 0x00000001, 0x00040000, 0x00040001, \r
73       0x01000000, 0x01000001, 0x01040000, 0x01040001, \r
74       0x00000002, 0x00000003, 0x00040002, 0x00040003, \r
75       0x01000002, 0x01000003, 0x01040002, 0x01040003, \r
76       0x00000200, 0x00000201, 0x00040200, 0x00040201, \r
77       0x01000200, 0x01000201, 0x01040200, 0x01040201, \r
78       0x00000202, 0x00000203, 0x00040202, 0x00040203, \r
79       0x01000202, 0x01000203, 0x01040202, 0x01040203, \r
80       0x08000000, 0x08000001, 0x08040000, 0x08040001, \r
81       0x09000000, 0x09000001, 0x09040000, 0x09040001, \r
82       0x08000002, 0x08000003, 0x08040002, 0x08040003, \r
83       0x09000002, 0x09000003, 0x09040002, 0x09040003, \r
84       0x08000200, 0x08000201, 0x08040200, 0x08040201, \r
85       0x09000200, 0x09000201, 0x09040200, 0x09040201, \r
86       0x08000202, 0x08000203, 0x08040202, 0x08040203, \r
87       0x09000202, 0x09000203, 0x09040202, 0x09040203, \r
88     },\r
89     {\r
90       /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */\r
91       0x00000000, 0x00100000, 0x00000100, 0x00100100, \r
92       0x00000008, 0x00100008, 0x00000108, 0x00100108, \r
93       0x00001000, 0x00101000, 0x00001100, 0x00101100, \r
94       0x00001008, 0x00101008, 0x00001108, 0x00101108, \r
95       0x04000000, 0x04100000, 0x04000100, 0x04100100, \r
96       0x04000008, 0x04100008, 0x04000108, 0x04100108, \r
97       0x04001000, 0x04101000, 0x04001100, 0x04101100, \r
98       0x04001008, 0x04101008, 0x04001108, 0x04101108, \r
99       0x00020000, 0x00120000, 0x00020100, 0x00120100, \r
100       0x00020008, 0x00120008, 0x00020108, 0x00120108, \r
101       0x00021000, 0x00121000, 0x00021100, 0x00121100, \r
102       0x00021008, 0x00121008, 0x00021108, 0x00121108, \r
103       0x04020000, 0x04120000, 0x04020100, 0x04120100, \r
104       0x04020008, 0x04120008, 0x04020108, 0x04120108, \r
105       0x04021000, 0x04121000, 0x04021100, 0x04121100, \r
106       0x04021008, 0x04121008, 0x04021108, 0x04121108, \r
107     },\r
108     {\r
109       /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */\r
110       0x00000000, 0x10000000, 0x00010000, 0x10010000, \r
111       0x00000004, 0x10000004, 0x00010004, 0x10010004, \r
112       0x20000000, 0x30000000, 0x20010000, 0x30010000, \r
113       0x20000004, 0x30000004, 0x20010004, 0x30010004, \r
114       0x00100000, 0x10100000, 0x00110000, 0x10110000, \r
115       0x00100004, 0x10100004, 0x00110004, 0x10110004, \r
116       0x20100000, 0x30100000, 0x20110000, 0x30110000, \r
117       0x20100004, 0x30100004, 0x20110004, 0x30110004, \r
118       0x00001000, 0x10001000, 0x00011000, 0x10011000, \r
119       0x00001004, 0x10001004, 0x00011004, 0x10011004, \r
120       0x20001000, 0x30001000, 0x20011000, 0x30011000, \r
121       0x20001004, 0x30001004, 0x20011004, 0x30011004, \r
122       0x00101000, 0x10101000, 0x00111000, 0x10111000, \r
123       0x00101004, 0x10101004, 0x00111004, 0x10111004, \r
124       0x20101000, 0x30101000, 0x20111000, 0x30111000, \r
125       0x20101004, 0x30101004, 0x20111004, 0x30111004, \r
126     },\r
127     {\r
128       /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */\r
129       0x00000000, 0x08000000, 0x00000008, 0x08000008, \r
130       0x00000400, 0x08000400, 0x00000408, 0x08000408, \r
131       0x00020000, 0x08020000, 0x00020008, 0x08020008, \r
132       0x00020400, 0x08020400, 0x00020408, 0x08020408, \r
133       0x00000001, 0x08000001, 0x00000009, 0x08000009, \r
134       0x00000401, 0x08000401, 0x00000409, 0x08000409, \r
135       0x00020001, 0x08020001, 0x00020009, 0x08020009, \r
136       0x00020401, 0x08020401, 0x00020409, 0x08020409, \r
137       0x02000000, 0x0A000000, 0x02000008, 0x0A000008, \r
138       0x02000400, 0x0A000400, 0x02000408, 0x0A000408, \r
139       0x02020000, 0x0A020000, 0x02020008, 0x0A020008, \r
140       0x02020400, 0x0A020400, 0x02020408, 0x0A020408, \r
141       0x02000001, 0x0A000001, 0x02000009, 0x0A000009, \r
142       0x02000401, 0x0A000401, 0x02000409, 0x0A000409, \r
143       0x02020001, 0x0A020001, 0x02020009, 0x0A020009, \r
144       0x02020401, 0x0A020401, 0x02020409, 0x0A020409, \r
145     },\r
146     {\r
147       /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */\r
148       0x00000000, 0x00000100, 0x00080000, 0x00080100, \r
149       0x01000000, 0x01000100, 0x01080000, 0x01080100, \r
150       0x00000010, 0x00000110, 0x00080010, 0x00080110, \r
151       0x01000010, 0x01000110, 0x01080010, 0x01080110, \r
152       0x00200000, 0x00200100, 0x00280000, 0x00280100, \r
153       0x01200000, 0x01200100, 0x01280000, 0x01280100, \r
154       0x00200010, 0x00200110, 0x00280010, 0x00280110, \r
155       0x01200010, 0x01200110, 0x01280010, 0x01280110, \r
156       0x00000200, 0x00000300, 0x00080200, 0x00080300, \r
157       0x01000200, 0x01000300, 0x01080200, 0x01080300, \r
158       0x00000210, 0x00000310, 0x00080210, 0x00080310, \r
159       0x01000210, 0x01000310, 0x01080210, 0x01080310, \r
160       0x00200200, 0x00200300, 0x00280200, 0x00280300, \r
161       0x01200200, 0x01200300, 0x01280200, 0x01280300, \r
162       0x00200210, 0x00200310, 0x00280210, 0x00280310, \r
163       0x01200210, 0x01200310, 0x01280210, 0x01280310, \r
164     },\r
165     {\r
166       /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */\r
167       0x00000000, 0x04000000, 0x00040000, 0x04040000, \r
168       0x00000002, 0x04000002, 0x00040002, 0x04040002, \r
169       0x00002000, 0x04002000, 0x00042000, 0x04042000, \r
170       0x00002002, 0x04002002, 0x00042002, 0x04042002, \r
171       0x00000020, 0x04000020, 0x00040020, 0x04040020, \r
172       0x00000022, 0x04000022, 0x00040022, 0x04040022, \r
173       0x00002020, 0x04002020, 0x00042020, 0x04042020, \r
174       0x00002022, 0x04002022, 0x00042022, 0x04042022, \r
175       0x00000800, 0x04000800, 0x00040800, 0x04040800, \r
176       0x00000802, 0x04000802, 0x00040802, 0x04040802, \r
177       0x00002800, 0x04002800, 0x00042800, 0x04042800, \r
178       0x00002802, 0x04002802, 0x00042802, 0x04042802, \r
179       0x00000820, 0x04000820, 0x00040820, 0x04040820, \r
180       0x00000822, 0x04000822, 0x00040822, 0x04040822, \r
181       0x00002820, 0x04002820, 0x00042820, 0x04042820, \r
182       0x00002822, 0x04002822, 0x00042822, 0x04042822, \r
183     }\r
184   };\r
185   \r
186   private static final int SPtrans[][] = {\r
187     {\r
188       /* nibble 0 */\r
189       0x00820200, 0x00020000, 0x80800000, 0x80820200,\r
190       0x00800000, 0x80020200, 0x80020000, 0x80800000,\r
191       0x80020200, 0x00820200, 0x00820000, 0x80000200,\r
192       0x80800200, 0x00800000, 0x00000000, 0x80020000,\r
193       0x00020000, 0x80000000, 0x00800200, 0x00020200,\r
194       0x80820200, 0x00820000, 0x80000200, 0x00800200,\r
195       0x80000000, 0x00000200, 0x00020200, 0x80820000,\r
196       0x00000200, 0x80800200, 0x80820000, 0x00000000,\r
197       0x00000000, 0x80820200, 0x00800200, 0x80020000,\r
198       0x00820200, 0x00020000, 0x80000200, 0x00800200,\r
199       0x80820000, 0x00000200, 0x00020200, 0x80800000,\r
200       0x80020200, 0x80000000, 0x80800000, 0x00820000,\r
201       0x80820200, 0x00020200, 0x00820000, 0x80800200,\r
202       0x00800000, 0x80000200, 0x80020000, 0x00000000,\r
203       0x00020000, 0x00800000, 0x80800200, 0x00820200,\r
204       0x80000000, 0x80820000, 0x00000200, 0x80020200,\r
205     },\r
206     {\r
207       /* nibble 1 */\r
208       0x10042004, 0x00000000, 0x00042000, 0x10040000,\r
209       0x10000004, 0x00002004, 0x10002000, 0x00042000,\r
210       0x00002000, 0x10040004, 0x00000004, 0x10002000,\r
211       0x00040004, 0x10042000, 0x10040000, 0x00000004,\r
212       0x00040000, 0x10002004, 0x10040004, 0x00002000,\r
213       0x00042004, 0x10000000, 0x00000000, 0x00040004,\r
214       0x10002004, 0x00042004, 0x10042000, 0x10000004,\r
215       0x10000000, 0x00040000, 0x00002004, 0x10042004,\r
216       0x00040004, 0x10042000, 0x10002000, 0x00042004,\r
217       0x10042004, 0x00040004, 0x10000004, 0x00000000,\r
218       0x10000000, 0x00002004, 0x00040000, 0x10040004,\r
219       0x00002000, 0x10000000, 0x00042004, 0x10002004,\r
220       0x10042000, 0x00002000, 0x00000000, 0x10000004,\r
221       0x00000004, 0x10042004, 0x00042000, 0x10040000,\r
222       0x10040004, 0x00040000, 0x00002004, 0x10002000,\r
223       0x10002004, 0x00000004, 0x10040000, 0x00042000,\r
224     },\r
225     {\r
226       /* nibble 2 */\r
227       0x41000000, 0x01010040, 0x00000040, 0x41000040,\r
228       0x40010000, 0x01000000, 0x41000040, 0x00010040,\r
229       0x01000040, 0x00010000, 0x01010000, 0x40000000,\r
230       0x41010040, 0x40000040, 0x40000000, 0x41010000,\r
231       0x00000000, 0x40010000, 0x01010040, 0x00000040,\r
232       0x40000040, 0x41010040, 0x00010000, 0x41000000,\r
233       0x41010000, 0x01000040, 0x40010040, 0x01010000,\r
234       0x00010040, 0x00000000, 0x01000000, 0x40010040,\r
235       0x01010040, 0x00000040, 0x40000000, 0x00010000,\r
236       0x40000040, 0x40010000, 0x01010000, 0x41000040,\r
237       0x00000000, 0x01010040, 0x00010040, 0x41010000,\r
238       0x40010000, 0x01000000, 0x41010040, 0x40000000,\r
239       0x40010040, 0x41000000, 0x01000000, 0x41010040,\r
240       0x00010000, 0x01000040, 0x41000040, 0x00010040,\r
241       0x01000040, 0x00000000, 0x41010000, 0x40000040,\r
242       0x41000000, 0x40010040, 0x00000040, 0x01010000,\r
243     },\r
244     {\r
245       /* nibble 3 */\r
246       0x00100402, 0x04000400, 0x00000002, 0x04100402,\r
247       0x00000000, 0x04100000, 0x04000402, 0x00100002,\r
248       0x04100400, 0x04000002, 0x04000000, 0x00000402,\r
249       0x04000002, 0x00100402, 0x00100000, 0x04000000,\r
250       0x04100002, 0x00100400, 0x00000400, 0x00000002,\r
251       0x00100400, 0x04000402, 0x04100000, 0x00000400,\r
252       0x00000402, 0x00000000, 0x00100002, 0x04100400,\r
253       0x04000400, 0x04100002, 0x04100402, 0x00100000,\r
254       0x04100002, 0x00000402, 0x00100000, 0x04000002,\r
255       0x00100400, 0x04000400, 0x00000002, 0x04100000,\r
256       0x04000402, 0x00000000, 0x00000400, 0x00100002,\r
257       0x00000000, 0x04100002, 0x04100400, 0x00000400,\r
258       0x04000000, 0x04100402, 0x00100402, 0x00100000,\r
259       0x04100402, 0x00000002, 0x04000400, 0x00100402,\r
260       0x00100002, 0x00100400, 0x04100000, 0x04000402,\r
261       0x00000402, 0x04000000, 0x04000002, 0x04100400,\r
262     },\r
263     {\r
264       /* nibble 4 */\r
265       0x02000000, 0x00004000, 0x00000100, 0x02004108,\r
266       0x02004008, 0x02000100, 0x00004108, 0x02004000,\r
267       0x00004000, 0x00000008, 0x02000008, 0x00004100,\r
268       0x02000108, 0x02004008, 0x02004100, 0x00000000,\r
269       0x00004100, 0x02000000, 0x00004008, 0x00000108,\r
270       0x02000100, 0x00004108, 0x00000000, 0x02000008,\r
271       0x00000008, 0x02000108, 0x02004108, 0x00004008,\r
272       0x02004000, 0x00000100, 0x00000108, 0x02004100,\r
273       0x02004100, 0x02000108, 0x00004008, 0x02004000,\r
274       0x00004000, 0x00000008, 0x02000008, 0x02000100,\r
275       0x02000000, 0x00004100, 0x02004108, 0x00000000,\r
276       0x00004108, 0x02000000, 0x00000100, 0x00004008,\r
277       0x02000108, 0x00000100, 0x00000000, 0x02004108,\r
278       0x02004008, 0x02004100, 0x00000108, 0x00004000,\r
279       0x00004100, 0x02004008, 0x02000100, 0x00000108,\r
280       0x00000008, 0x00004108, 0x02004000, 0x02000008,\r
281     },\r
282     {\r
283       /* nibble 5 */\r
284       0x20000010, 0x00080010, 0x00000000, 0x20080800,\r
285       0x00080010, 0x00000800, 0x20000810, 0x00080000,\r
286       0x00000810, 0x20080810, 0x00080800, 0x20000000,\r
287       0x20000800, 0x20000010, 0x20080000, 0x00080810,\r
288       0x00080000, 0x20000810, 0x20080010, 0x00000000,\r
289       0x00000800, 0x00000010, 0x20080800, 0x20080010,\r
290       0x20080810, 0x20080000, 0x20000000, 0x00000810,\r
291       0x00000010, 0x00080800, 0x00080810, 0x20000800,\r
292       0x00000810, 0x20000000, 0x20000800, 0x00080810,\r
293       0x20080800, 0x00080010, 0x00000000, 0x20000800,\r
294       0x20000000, 0x00000800, 0x20080010, 0x00080000,\r
295       0x00080010, 0x20080810, 0x00080800, 0x00000010,\r
296       0x20080810, 0x00080800, 0x00080000, 0x20000810,\r
297       0x20000010, 0x20080000, 0x00080810, 0x00000000,\r
298       0x00000800, 0x20000010, 0x20000810, 0x20080800,\r
299       0x20080000, 0x00000810, 0x00000010, 0x20080010,\r
300     },\r
301     {\r
302       /* nibble 6 */\r
303       0x00001000, 0x00000080, 0x00400080, 0x00400001,\r
304       0x00401081, 0x00001001, 0x00001080, 0x00000000,\r
305       0x00400000, 0x00400081, 0x00000081, 0x00401000,\r
306       0x00000001, 0x00401080, 0x00401000, 0x00000081,\r
307       0x00400081, 0x00001000, 0x00001001, 0x00401081,\r
308       0x00000000, 0x00400080, 0x00400001, 0x00001080,\r
309       0x00401001, 0x00001081, 0x00401080, 0x00000001,\r
310       0x00001081, 0x00401001, 0x00000080, 0x00400000,\r
311       0x00001081, 0x00401000, 0x00401001, 0x00000081,\r
312       0x00001000, 0x00000080, 0x00400000, 0x00401001,\r
313       0x00400081, 0x00001081, 0x00001080, 0x00000000,\r
314       0x00000080, 0x00400001, 0x00000001, 0x00400080,\r
315       0x00000000, 0x00400081, 0x00400080, 0x00001080,\r
316       0x00000081, 0x00001000, 0x00401081, 0x00400000,\r
317       0x00401080, 0x00000001, 0x00001001, 0x00401081,\r
318       0x00400001, 0x00401080, 0x00401000, 0x00001001,\r
319     },\r
320     {\r
321       /* nibble 7 */\r
322       0x08200020, 0x08208000, 0x00008020, 0x00000000,\r
323       0x08008000, 0x00200020, 0x08200000, 0x08208020,\r
324       0x00000020, 0x08000000, 0x00208000, 0x00008020,\r
325       0x00208020, 0x08008020, 0x08000020, 0x08200000,\r
326       0x00008000, 0x00208020, 0x00200020, 0x08008000,\r
327       0x08208020, 0x08000020, 0x00000000, 0x00208000,\r
328       0x08000000, 0x00200000, 0x08008020, 0x08200020,\r
329       0x00200000, 0x00008000, 0x08208000, 0x00000020,\r
330       0x00200000, 0x00008000, 0x08000020, 0x08208020,\r
331       0x00008020, 0x08000000, 0x00000000, 0x00208000,\r
332       0x08200020, 0x08008020, 0x08008000, 0x00200020,\r
333       0x08208000, 0x00000020, 0x00200020, 0x08008000,\r
334       0x08208020, 0x00200000, 0x08200000, 0x08000020,\r
335       0x00208000, 0x00008020, 0x08008020, 0x08200000,\r
336       0x00000020, 0x08208000, 0x00208020, 0x00000000,\r
337       0x08000000, 0x08200020, 0x00008000, 0x00208020\r
338     }\r
339   };\r
340   \r
341   private static final int byteToUnsigned(byte b) {\r
342     int value = (int) b;\r
343     return (value >= 0) ? value : value + 256;\r
344   }\r
345 \r
346   private static int fourBytesToInt(byte b[], int offset) {\r
347     return byteToUnsigned(b[offset++]) \r
348       | (byteToUnsigned(b[offset++]) <<  8) \r
349       | (byteToUnsigned(b[offset++]) << 16) \r
350       | (byteToUnsigned(b[offset]) << 24);\r
351   }\r
352 \r
353   private static final void intToFourBytes(int iValue, byte b[], int offset) {\r
354     b[offset++] = (byte)((iValue)        & 0xff);\r
355     b[offset++] = (byte)((iValue >>> 8 ) & 0xff);\r
356     b[offset++] = (byte)((iValue >>> 16) & 0xff);\r
357     b[offset] = (byte)((iValue >>> 24) & 0xff);\r
358   }\r
359   \r
360   private static final void PERM_OP(int a, int b, int n, int m, int results[]) {\r
361     int t;\r
362 \r
363     t = ((a >>> n) ^ b) & m;\r
364     a ^= t << n;\r
365     b ^= t;\r
366 \r
367     results[0] = a;\r
368     results[1] = b;\r
369   }\r
370 \r
371   private static final int HPERM_OP(int a, int n, int m) {\r
372     int t;\r
373     \r
374     t = ((a << (16 - n)) ^ a) & m;\r
375     a = a ^ t ^ (t >>> (16 - n));\r
376     \r
377     return a;\r
378   }\r
379 \r
380   private static int [] des_set_key(byte key[]) {\r
381     int schedule[] = new int [ITERATIONS * 2];\r
382     \r
383     int c = fourBytesToInt(key, 0);\r
384     int d = fourBytesToInt(key, 4);\r
385     \r
386     int results[] = new int[2];\r
387 \r
388     PERM_OP(d, c, 4, 0x0f0f0f0f, results);\r
389     d = results[0]; c = results[1];\r
390     \r
391     c = HPERM_OP(c, -2, 0xcccc0000);\r
392     d = HPERM_OP(d, -2, 0xcccc0000);\r
393     \r
394     PERM_OP(d, c, 1, 0x55555555, results);\r
395     d = results[0]; c = results[1];\r
396     \r
397     PERM_OP(c, d, 8, 0x00ff00ff, results);\r
398     c = results[0]; d = results[1];\r
399     \r
400     PERM_OP(d, c, 1, 0x55555555, results);\r
401     d = results[0]; c = results[1];\r
402     \r
403     d = (((d & 0x000000ff) <<  16) |  (d & 0x0000ff00)     |\r
404          ((d & 0x00ff0000) >>> 16) | ((c & 0xf0000000) >>> 4));\r
405     c &= 0x0fffffff;\r
406     \r
407     int s, t;\r
408     int j = 0;\r
409     \r
410     for(int i = 0; i < ITERATIONS; i ++) {\r
411       if(shifts2[i]) {\r
412         c = (c >>> 2) | (c << 26);\r
413         d = (d >>> 2) | (d << 26);\r
414       } else {\r
415         c = (c >>> 1) | (c << 27);\r
416         d = (d >>> 1) | (d << 27);\r
417       }\r
418       \r
419       c &= 0x0fffffff;\r
420       d &= 0x0fffffff;\r
421       \r
422       s = skb[0][ (c       ) & 0x3f                       ]|\r
423         skb[1][((c >>>  6) & 0x03) | ((c >>>  7) & 0x3c)]|\r
424         skb[2][((c >>> 13) & 0x0f) | ((c >>> 14) & 0x30)]|\r
425         skb[3][((c >>> 20) & 0x01) | ((c >>> 21) & 0x06) |\r
426                                    ((c >>> 22) & 0x38)];\r
427 \r
428       t = skb[4][ (d     )  & 0x3f                       ]|\r
429         skb[5][((d >>> 7) & 0x03) | ((d >>>  8) & 0x3c)]|\r
430         skb[6][ (d >>>15) & 0x3f                       ]|\r
431         skb[7][((d >>>21) & 0x0f) | ((d >>> 22) & 0x30)];\r
432       \r
433       schedule[j++] = ((t <<  16) | (s & 0x0000ffff)) & 0xffffffff;\r
434       s             = ((s >>> 16) | (t & 0xffff0000));\r
435       \r
436       s             = (s << 4) | (s >>> 28);\r
437       schedule[j++] = s & 0xffffffff;\r
438     }\r
439     return schedule;\r
440   }\r
441 \r
442   private static final int D_ENUnixCrypt(int L, int R, int S, int E0, int E1, int s[]) {\r
443     int t, u, v;\r
444     \r
445     v = R ^ (R >>> 16);\r
446     u = v & E0;\r
447     v = v & E1;\r
448     u = (u ^ (u << 16)) ^ R ^ s[S];\r
449     t = (v ^ (v << 16)) ^ R ^ s[S + 1];\r
450     t = (t >>> 4) | (t << 28);\r
451     \r
452     L ^= SPtrans[1][(t       ) & 0x3f] |\r
453       SPtrans[3][(t >>>  8) & 0x3f] |\r
454       SPtrans[5][(t >>> 16) & 0x3f] |\r
455       SPtrans[7][(t >>> 24) & 0x3f] |\r
456       SPtrans[0][(u       ) & 0x3f] |\r
457       SPtrans[2][(u >>>  8) & 0x3f] |\r
458       SPtrans[4][(u >>> 16) & 0x3f] |\r
459       SPtrans[6][(u >>> 24) & 0x3f];\r
460 \r
461     return L;\r
462   }\r
463   \r
464   private static final int [] body(int schedule[], int Eswap0, int Eswap1) \r
465   {\r
466     int left = 0;\r
467     int right = 0;\r
468     int t     = 0;\r
469 \r
470     for (int j = 0; j < 25; j ++) {\r
471       for (int i = 0; i < ITERATIONS * 2; i += 4) {\r
472         left  = D_ENUnixCrypt(left,  right, i,     Eswap0, Eswap1, schedule);\r
473         right = D_ENUnixCrypt(right, left,  i + 2, Eswap0, Eswap1, schedule);\r
474       }\r
475       t     = left; \r
476       left  = right; \r
477       right = t;\r
478     }\r
479     \r
480     t = right;\r
481 \r
482     right = (left >>> 1) | (left << 31);\r
483     left  = (t    >>> 1) | (t    << 31);\r
484     \r
485     left  &= 0xffffffff;\r
486     right &= 0xffffffff;\r
487 \r
488     int results[] = new int[2];\r
489 \r
490     PERM_OP(right, left, 1, 0x55555555, results); \r
491     right = results[0]; left = results[1];\r
492     \r
493     PERM_OP(left, right, 8, 0x00ff00ff, results); \r
494     left = results[0]; right = results[1];\r
495 \r
496     PERM_OP(right, left, 2, 0x33333333, results); \r
497     right = results[0]; left = results[1];\r
498     \r
499     PERM_OP(left, right, 16, 0x0000ffff, results);\r
500     left = results[0]; right = results[1];\r
501     \r
502     PERM_OP(right, left, 4, 0x0f0f0f0f, results);\r
503     right = results[0]; left = results[1];\r
504     \r
505     int out[] = new int[2];\r
506     \r
507     out[0] = left; \r
508     out[1] = right;\r
509     \r
510     return out;\r
511   }\r
512 \r
513   public static final String alphabet = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";\r
514 \r
515   public static final String encrypt(String salt, String original) \r
516   {\r
517     // wwb -- Should do some sanity checks: salt needs to be 2 chars, in alpha.\r
518     while(salt.length() < 2)\r
519       salt += "A";\r
520 \r
521     char[] buffer = new char [13];\r
522 \r
523     char charZero = salt.charAt(0);\r
524     char charOne  = salt.charAt(1);\r
525     \r
526     buffer[0] = charZero;\r
527     buffer[1] = charOne;\r
528 \r
529     int Eswap0 = alphabet.indexOf(charZero);\r
530     int Eswap1 = alphabet.indexOf(charOne) << 4;\r
531     byte key[] = new byte[8];\r
532     \r
533     for(int i = 0; i < key.length; i ++)\r
534       key[i] = (byte)0;\r
535     \r
536     for(int i = 0; i < key.length && i < original.length(); i ++)\r
537       key[i] = (byte) (((int) original.charAt(i)) << 1);\r
538 \r
539     int schedule[] = des_set_key(key);\r
540     int out[]      = body(schedule, Eswap0, Eswap1);\r
541     \r
542     byte b[] = new byte[9];\r
543     \r
544     intToFourBytes(out[0], b, 0);\r
545     intToFourBytes(out[1], b, 4);\r
546     b[8] = 0;\r
547 \r
548     for(int i = 2, y = 0, u = 0x80; i < 13; i ++) {\r
549       for(int j = 0, c = 0; j < 6; j ++) {\r
550         c <<= 1;\r
551 \r
552         if(((int)b[y] & u) != 0)\r
553           c |= 1;\r
554 \r
555         u >>>= 1;\r
556         \r
557         if (u == 0) {\r
558           y++;\r
559           u = 0x80;\r
560         }\r
561         buffer[i] = alphabet.charAt(c);\r
562       }\r
563     }\r
564     return new String(buffer);\r
565   }\r
566   \r
567   public static void main(String [] args)\r
568   {\r
569           if ( (1 == args.length) && ("list".equalsIgnoreCase(args[0])) )\r
570           {\r
571                   StringBuffer listChars = new StringBuffer(alphabet);\r
572                   final String password = "italianroast";\r
573                   int salt = 1;\r
574                   ArrayList<String []> pws = new ArrayList<String []>();\r
575                   while( listChars.length() > 0 )\r
576                   {\r
577                           int startLen = listChars.length();\r
578                           String pw = UnixCrypt.encrypt(Integer.toString(salt), password);\r
579                           for( int i = 0; i < pw.length(); ++i )\r
580                           {\r
581                                   int pos = listChars.indexOf(pw.substring(i, i+1));\r
582                                   if( pos >= 0 )\r
583                                           listChars.deleteCharAt(pos);                            \r
584                           }\r
585                           if( listChars.length() == startLen )\r
586                                   ++salt;\r
587                           else\r
588                                   pws.add(new String [] { password, pw });\r
589                   }\r
590                   for( String [] pw : pws )\r
591                           System.out.println(pw[0] + " : " + pw[1]);\r
592           }\r
593           else if ( 2 == args.length )\r
594           {\r
595                   System.out.println(UnixCrypt.encrypt(args[0], args[1]));\r
596           }\r
597           else\r
598           {\r
599                   System.out.println("usage: UnixCrypt <salt> <password>");\r
600                   System.out.println("or: \"UnixCrypt list\" to generate a list of password with all possible characters.");\r
601           }\r
602   }\r
603   \r
604 }\r