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