001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.crypt;
020
021/****************************************************************************
022 * JCrypt.java
023 *
024 * Java-based implementation of the unix crypt command
025 *
026 * Based upon C source code written by Eric Young, eay@psych.uq.oz.au
027 *
028 ****************************************************************************/
029
030public final class JCrypt
031{
032   private JCrypt() {}
033
034   private static final int ITERATIONS = 16;
035
036   private static final int con_salt[] =
037   {
038      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
039      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
040      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
041      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
042      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
043      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
044      0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
045      0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 
046      0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 
047      0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 
048      0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 
049      0x23, 0x24, 0x25, 0x20, 0x21, 0x22, 0x23, 0x24, 
050      0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 
051      0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 
052      0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 
053      0x3D, 0x3E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 
054   };
055
056   private static final boolean shifts2[] =
057   {
058      false, false, true, true, true, true, true, true,
059      false, true,  true, true, true, true, true, false
060   };
061
062   private static final int skb[][] =
063   {
064      {
065         /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
066         0x00000000, 0x00000010, 0x20000000, 0x20000010, 
067         0x00010000, 0x00010010, 0x20010000, 0x20010010, 
068         0x00000800, 0x00000810, 0x20000800, 0x20000810, 
069         0x00010800, 0x00010810, 0x20010800, 0x20010810, 
070         0x00000020, 0x00000030, 0x20000020, 0x20000030, 
071         0x00010020, 0x00010030, 0x20010020, 0x20010030, 
072         0x00000820, 0x00000830, 0x20000820, 0x20000830, 
073         0x00010820, 0x00010830, 0x20010820, 0x20010830, 
074         0x00080000, 0x00080010, 0x20080000, 0x20080010, 
075         0x00090000, 0x00090010, 0x20090000, 0x20090010, 
076         0x00080800, 0x00080810, 0x20080800, 0x20080810, 
077         0x00090800, 0x00090810, 0x20090800, 0x20090810, 
078         0x00080020, 0x00080030, 0x20080020, 0x20080030, 
079         0x00090020, 0x00090030, 0x20090020, 0x20090030, 
080         0x00080820, 0x00080830, 0x20080820, 0x20080830, 
081         0x00090820, 0x00090830, 0x20090820, 0x20090830, 
082      },
083      {
084         /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
085         0x00000000, 0x02000000, 0x00002000, 0x02002000, 
086         0x00200000, 0x02200000, 0x00202000, 0x02202000, 
087         0x00000004, 0x02000004, 0x00002004, 0x02002004, 
088         0x00200004, 0x02200004, 0x00202004, 0x02202004, 
089         0x00000400, 0x02000400, 0x00002400, 0x02002400, 
090         0x00200400, 0x02200400, 0x00202400, 0x02202400, 
091         0x00000404, 0x02000404, 0x00002404, 0x02002404, 
092         0x00200404, 0x02200404, 0x00202404, 0x02202404, 
093         0x10000000, 0x12000000, 0x10002000, 0x12002000, 
094         0x10200000, 0x12200000, 0x10202000, 0x12202000, 
095         0x10000004, 0x12000004, 0x10002004, 0x12002004, 
096         0x10200004, 0x12200004, 0x10202004, 0x12202004, 
097         0x10000400, 0x12000400, 0x10002400, 0x12002400, 
098         0x10200400, 0x12200400, 0x10202400, 0x12202400, 
099         0x10000404, 0x12000404, 0x10002404, 0x12002404, 
100         0x10200404, 0x12200404, 0x10202404, 0x12202404, 
101      },
102      {
103         /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
104         0x00000000, 0x00000001, 0x00040000, 0x00040001, 
105         0x01000000, 0x01000001, 0x01040000, 0x01040001, 
106         0x00000002, 0x00000003, 0x00040002, 0x00040003, 
107         0x01000002, 0x01000003, 0x01040002, 0x01040003, 
108         0x00000200, 0x00000201, 0x00040200, 0x00040201, 
109         0x01000200, 0x01000201, 0x01040200, 0x01040201, 
110         0x00000202, 0x00000203, 0x00040202, 0x00040203, 
111         0x01000202, 0x01000203, 0x01040202, 0x01040203, 
112         0x08000000, 0x08000001, 0x08040000, 0x08040001, 
113         0x09000000, 0x09000001, 0x09040000, 0x09040001, 
114         0x08000002, 0x08000003, 0x08040002, 0x08040003, 
115         0x09000002, 0x09000003, 0x09040002, 0x09040003, 
116         0x08000200, 0x08000201, 0x08040200, 0x08040201, 
117         0x09000200, 0x09000201, 0x09040200, 0x09040201, 
118         0x08000202, 0x08000203, 0x08040202, 0x08040203, 
119         0x09000202, 0x09000203, 0x09040202, 0x09040203, 
120      },
121      {
122         /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
123         0x00000000, 0x00100000, 0x00000100, 0x00100100, 
124         0x00000008, 0x00100008, 0x00000108, 0x00100108, 
125         0x00001000, 0x00101000, 0x00001100, 0x00101100, 
126         0x00001008, 0x00101008, 0x00001108, 0x00101108, 
127         0x04000000, 0x04100000, 0x04000100, 0x04100100, 
128         0x04000008, 0x04100008, 0x04000108, 0x04100108, 
129         0x04001000, 0x04101000, 0x04001100, 0x04101100, 
130         0x04001008, 0x04101008, 0x04001108, 0x04101108, 
131         0x00020000, 0x00120000, 0x00020100, 0x00120100, 
132         0x00020008, 0x00120008, 0x00020108, 0x00120108, 
133         0x00021000, 0x00121000, 0x00021100, 0x00121100, 
134         0x00021008, 0x00121008, 0x00021108, 0x00121108, 
135         0x04020000, 0x04120000, 0x04020100, 0x04120100, 
136         0x04020008, 0x04120008, 0x04020108, 0x04120108, 
137         0x04021000, 0x04121000, 0x04021100, 0x04121100, 
138         0x04021008, 0x04121008, 0x04021108, 0x04121108, 
139      },
140      {
141         /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
142         0x00000000, 0x10000000, 0x00010000, 0x10010000, 
143         0x00000004, 0x10000004, 0x00010004, 0x10010004, 
144         0x20000000, 0x30000000, 0x20010000, 0x30010000, 
145         0x20000004, 0x30000004, 0x20010004, 0x30010004, 
146         0x00100000, 0x10100000, 0x00110000, 0x10110000, 
147         0x00100004, 0x10100004, 0x00110004, 0x10110004, 
148         0x20100000, 0x30100000, 0x20110000, 0x30110000, 
149         0x20100004, 0x30100004, 0x20110004, 0x30110004, 
150         0x00001000, 0x10001000, 0x00011000, 0x10011000, 
151         0x00001004, 0x10001004, 0x00011004, 0x10011004, 
152         0x20001000, 0x30001000, 0x20011000, 0x30011000, 
153         0x20001004, 0x30001004, 0x20011004, 0x30011004, 
154         0x00101000, 0x10101000, 0x00111000, 0x10111000, 
155         0x00101004, 0x10101004, 0x00111004, 0x10111004, 
156         0x20101000, 0x30101000, 0x20111000, 0x30111000, 
157         0x20101004, 0x30101004, 0x20111004, 0x30111004, 
158      },
159      {
160         /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
161         0x00000000, 0x08000000, 0x00000008, 0x08000008, 
162         0x00000400, 0x08000400, 0x00000408, 0x08000408, 
163         0x00020000, 0x08020000, 0x00020008, 0x08020008, 
164         0x00020400, 0x08020400, 0x00020408, 0x08020408, 
165         0x00000001, 0x08000001, 0x00000009, 0x08000009, 
166         0x00000401, 0x08000401, 0x00000409, 0x08000409, 
167         0x00020001, 0x08020001, 0x00020009, 0x08020009, 
168         0x00020401, 0x08020401, 0x00020409, 0x08020409, 
169         0x02000000, 0x0A000000, 0x02000008, 0x0A000008, 
170         0x02000400, 0x0A000400, 0x02000408, 0x0A000408, 
171         0x02020000, 0x0A020000, 0x02020008, 0x0A020008, 
172         0x02020400, 0x0A020400, 0x02020408, 0x0A020408, 
173         0x02000001, 0x0A000001, 0x02000009, 0x0A000009, 
174         0x02000401, 0x0A000401, 0x02000409, 0x0A000409, 
175         0x02020001, 0x0A020001, 0x02020009, 0x0A020009, 
176         0x02020401, 0x0A020401, 0x02020409, 0x0A020409, 
177      },
178      {
179         /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
180         0x00000000, 0x00000100, 0x00080000, 0x00080100, 
181         0x01000000, 0x01000100, 0x01080000, 0x01080100, 
182         0x00000010, 0x00000110, 0x00080010, 0x00080110, 
183         0x01000010, 0x01000110, 0x01080010, 0x01080110, 
184         0x00200000, 0x00200100, 0x00280000, 0x00280100, 
185         0x01200000, 0x01200100, 0x01280000, 0x01280100, 
186         0x00200010, 0x00200110, 0x00280010, 0x00280110, 
187         0x01200010, 0x01200110, 0x01280010, 0x01280110, 
188         0x00000200, 0x00000300, 0x00080200, 0x00080300, 
189         0x01000200, 0x01000300, 0x01080200, 0x01080300, 
190         0x00000210, 0x00000310, 0x00080210, 0x00080310, 
191         0x01000210, 0x01000310, 0x01080210, 0x01080310, 
192         0x00200200, 0x00200300, 0x00280200, 0x00280300, 
193         0x01200200, 0x01200300, 0x01280200, 0x01280300, 
194         0x00200210, 0x00200310, 0x00280210, 0x00280310, 
195         0x01200210, 0x01200310, 0x01280210, 0x01280310, 
196      },
197      {
198         /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
199         0x00000000, 0x04000000, 0x00040000, 0x04040000, 
200         0x00000002, 0x04000002, 0x00040002, 0x04040002, 
201         0x00002000, 0x04002000, 0x00042000, 0x04042000, 
202         0x00002002, 0x04002002, 0x00042002, 0x04042002, 
203         0x00000020, 0x04000020, 0x00040020, 0x04040020, 
204         0x00000022, 0x04000022, 0x00040022, 0x04040022, 
205         0x00002020, 0x04002020, 0x00042020, 0x04042020, 
206         0x00002022, 0x04002022, 0x00042022, 0x04042022, 
207         0x00000800, 0x04000800, 0x00040800, 0x04040800, 
208         0x00000802, 0x04000802, 0x00040802, 0x04040802, 
209         0x00002800, 0x04002800, 0x00042800, 0x04042800, 
210         0x00002802, 0x04002802, 0x00042802, 0x04042802, 
211         0x00000820, 0x04000820, 0x00040820, 0x04040820, 
212         0x00000822, 0x04000822, 0x00040822, 0x04040822, 
213         0x00002820, 0x04002820, 0x00042820, 0x04042820, 
214         0x00002822, 0x04002822, 0x00042822, 0x04042822, 
215      },
216   };
217
218   private static final int SPtrans[][] =
219   {
220      {
221         /* nibble 0 */
222         0x00820200, 0x00020000, 0x80800000, 0x80820200,
223         0x00800000, 0x80020200, 0x80020000, 0x80800000,
224         0x80020200, 0x00820200, 0x00820000, 0x80000200,
225         0x80800200, 0x00800000, 0x00000000, 0x80020000,
226         0x00020000, 0x80000000, 0x00800200, 0x00020200,
227         0x80820200, 0x00820000, 0x80000200, 0x00800200,
228         0x80000000, 0x00000200, 0x00020200, 0x80820000,
229         0x00000200, 0x80800200, 0x80820000, 0x00000000,
230         0x00000000, 0x80820200, 0x00800200, 0x80020000,
231         0x00820200, 0x00020000, 0x80000200, 0x00800200,
232         0x80820000, 0x00000200, 0x00020200, 0x80800000,
233         0x80020200, 0x80000000, 0x80800000, 0x00820000,
234         0x80820200, 0x00020200, 0x00820000, 0x80800200,
235         0x00800000, 0x80000200, 0x80020000, 0x00000000,
236         0x00020000, 0x00800000, 0x80800200, 0x00820200,
237         0x80000000, 0x80820000, 0x00000200, 0x80020200,
238      },
239      {
240         /* nibble 1 */
241         0x10042004, 0x00000000, 0x00042000, 0x10040000,
242         0x10000004, 0x00002004, 0x10002000, 0x00042000,
243         0x00002000, 0x10040004, 0x00000004, 0x10002000,
244         0x00040004, 0x10042000, 0x10040000, 0x00000004,
245         0x00040000, 0x10002004, 0x10040004, 0x00002000,
246         0x00042004, 0x10000000, 0x00000000, 0x00040004,
247         0x10002004, 0x00042004, 0x10042000, 0x10000004,
248         0x10000000, 0x00040000, 0x00002004, 0x10042004,
249         0x00040004, 0x10042000, 0x10002000, 0x00042004,
250         0x10042004, 0x00040004, 0x10000004, 0x00000000,
251         0x10000000, 0x00002004, 0x00040000, 0x10040004,
252         0x00002000, 0x10000000, 0x00042004, 0x10002004,
253         0x10042000, 0x00002000, 0x00000000, 0x10000004,
254         0x00000004, 0x10042004, 0x00042000, 0x10040000,
255         0x10040004, 0x00040000, 0x00002004, 0x10002000,
256         0x10002004, 0x00000004, 0x10040000, 0x00042000,
257      },
258      {
259         /* nibble 2 */
260         0x41000000, 0x01010040, 0x00000040, 0x41000040,
261         0x40010000, 0x01000000, 0x41000040, 0x00010040,
262         0x01000040, 0x00010000, 0x01010000, 0x40000000,
263         0x41010040, 0x40000040, 0x40000000, 0x41010000,
264         0x00000000, 0x40010000, 0x01010040, 0x00000040,
265         0x40000040, 0x41010040, 0x00010000, 0x41000000,
266         0x41010000, 0x01000040, 0x40010040, 0x01010000,
267         0x00010040, 0x00000000, 0x01000000, 0x40010040,
268         0x01010040, 0x00000040, 0x40000000, 0x00010000,
269         0x40000040, 0x40010000, 0x01010000, 0x41000040,
270         0x00000000, 0x01010040, 0x00010040, 0x41010000,
271         0x40010000, 0x01000000, 0x41010040, 0x40000000,
272         0x40010040, 0x41000000, 0x01000000, 0x41010040,
273         0x00010000, 0x01000040, 0x41000040, 0x00010040,
274         0x01000040, 0x00000000, 0x41010000, 0x40000040,
275         0x41000000, 0x40010040, 0x00000040, 0x01010000,
276      },
277      {
278         /* nibble 3 */
279         0x00100402, 0x04000400, 0x00000002, 0x04100402,
280         0x00000000, 0x04100000, 0x04000402, 0x00100002,
281         0x04100400, 0x04000002, 0x04000000, 0x00000402,
282         0x04000002, 0x00100402, 0x00100000, 0x04000000,
283         0x04100002, 0x00100400, 0x00000400, 0x00000002,
284         0x00100400, 0x04000402, 0x04100000, 0x00000400,
285         0x00000402, 0x00000000, 0x00100002, 0x04100400,
286         0x04000400, 0x04100002, 0x04100402, 0x00100000,
287         0x04100002, 0x00000402, 0x00100000, 0x04000002,
288         0x00100400, 0x04000400, 0x00000002, 0x04100000,
289         0x04000402, 0x00000000, 0x00000400, 0x00100002,
290         0x00000000, 0x04100002, 0x04100400, 0x00000400,
291         0x04000000, 0x04100402, 0x00100402, 0x00100000,
292         0x04100402, 0x00000002, 0x04000400, 0x00100402,
293         0x00100002, 0x00100400, 0x04100000, 0x04000402,
294         0x00000402, 0x04000000, 0x04000002, 0x04100400,
295      },
296      {
297         /* nibble 4 */
298         0x02000000, 0x00004000, 0x00000100, 0x02004108,
299         0x02004008, 0x02000100, 0x00004108, 0x02004000,
300         0x00004000, 0x00000008, 0x02000008, 0x00004100,
301         0x02000108, 0x02004008, 0x02004100, 0x00000000,
302         0x00004100, 0x02000000, 0x00004008, 0x00000108,
303         0x02000100, 0x00004108, 0x00000000, 0x02000008,
304         0x00000008, 0x02000108, 0x02004108, 0x00004008,
305         0x02004000, 0x00000100, 0x00000108, 0x02004100,
306         0x02004100, 0x02000108, 0x00004008, 0x02004000,
307         0x00004000, 0x00000008, 0x02000008, 0x02000100,
308         0x02000000, 0x00004100, 0x02004108, 0x00000000,
309         0x00004108, 0x02000000, 0x00000100, 0x00004008,
310         0x02000108, 0x00000100, 0x00000000, 0x02004108,
311         0x02004008, 0x02004100, 0x00000108, 0x00004000,
312         0x00004100, 0x02004008, 0x02000100, 0x00000108,
313         0x00000008, 0x00004108, 0x02004000, 0x02000008,
314      },
315      {
316         /* nibble 5 */
317         0x20000010, 0x00080010, 0x00000000, 0x20080800,
318         0x00080010, 0x00000800, 0x20000810, 0x00080000,
319         0x00000810, 0x20080810, 0x00080800, 0x20000000,
320         0x20000800, 0x20000010, 0x20080000, 0x00080810,
321         0x00080000, 0x20000810, 0x20080010, 0x00000000,
322         0x00000800, 0x00000010, 0x20080800, 0x20080010,
323         0x20080810, 0x20080000, 0x20000000, 0x00000810,
324         0x00000010, 0x00080800, 0x00080810, 0x20000800,
325         0x00000810, 0x20000000, 0x20000800, 0x00080810,
326         0x20080800, 0x00080010, 0x00000000, 0x20000800,
327         0x20000000, 0x00000800, 0x20080010, 0x00080000,
328         0x00080010, 0x20080810, 0x00080800, 0x00000010,
329         0x20080810, 0x00080800, 0x00080000, 0x20000810,
330         0x20000010, 0x20080000, 0x00080810, 0x00000000,
331         0x00000800, 0x20000010, 0x20000810, 0x20080800,
332         0x20080000, 0x00000810, 0x00000010, 0x20080010,
333      },
334      {
335         /* nibble 6 */
336         0x00001000, 0x00000080, 0x00400080, 0x00400001,
337         0x00401081, 0x00001001, 0x00001080, 0x00000000,
338         0x00400000, 0x00400081, 0x00000081, 0x00401000,
339         0x00000001, 0x00401080, 0x00401000, 0x00000081,
340         0x00400081, 0x00001000, 0x00001001, 0x00401081,
341         0x00000000, 0x00400080, 0x00400001, 0x00001080,
342         0x00401001, 0x00001081, 0x00401080, 0x00000001,
343         0x00001081, 0x00401001, 0x00000080, 0x00400000,
344         0x00001081, 0x00401000, 0x00401001, 0x00000081,
345         0x00001000, 0x00000080, 0x00400000, 0x00401001,
346         0x00400081, 0x00001081, 0x00001080, 0x00000000,
347         0x00000080, 0x00400001, 0x00000001, 0x00400080,
348         0x00000000, 0x00400081, 0x00400080, 0x00001080,
349         0x00000081, 0x00001000, 0x00401081, 0x00400000,
350         0x00401080, 0x00000001, 0x00001001, 0x00401081,
351         0x00400001, 0x00401080, 0x00401000, 0x00001001,
352      },
353      {
354         /* nibble 7 */
355         0x08200020, 0x08208000, 0x00008020, 0x00000000,
356         0x08008000, 0x00200020, 0x08200000, 0x08208020,
357         0x00000020, 0x08000000, 0x00208000, 0x00008020,
358         0x00208020, 0x08008020, 0x08000020, 0x08200000,
359         0x00008000, 0x00208020, 0x00200020, 0x08008000,
360         0x08208020, 0x08000020, 0x00000000, 0x00208000,
361         0x08000000, 0x00200000, 0x08008020, 0x08200020,
362         0x00200000, 0x00008000, 0x08208000, 0x00000020,
363         0x00200000, 0x00008000, 0x08000020, 0x08208020,
364         0x00008020, 0x08000000, 0x00000000, 0x00208000,
365         0x08200020, 0x08008020, 0x08008000, 0x00200020,
366         0x08208000, 0x00000020, 0x00200020, 0x08008000,
367         0x08208020, 0x00200000, 0x08200000, 0x08000020,
368         0x00208000, 0x00008020, 0x08008020, 0x08200000,
369         0x00000020, 0x08208000, 0x00208020, 0x00000000,
370         0x08000000, 0x08200020, 0x00008000, 0x00208020
371      }
372   };
373
374   private static final int cov_2char[] =
375   {
376      0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 
377      0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 
378      0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 
379      0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 
380      0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 
381      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 
382      0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 
383      0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
384   };
385
386   private static final int byteToUnsigned(byte b)
387   {
388      int value = b;
389
390      return(value >= 0 ? value : value + 256);
391   }
392
393   private static int fourBytesToInt(byte b[], int offset)
394   {
395      int value;
396
397      value  =  byteToUnsigned(b[offset++]);
398      value |= (byteToUnsigned(b[offset++]) <<  8);
399      value |= (byteToUnsigned(b[offset++]) << 16);
400      value |= (byteToUnsigned(b[offset++]) << 24);
401
402      return(value);
403   }
404
405   private static final void intToFourBytes(int iValue, byte b[], int offset)
406   {
407      b[offset++] = (byte)((iValue)        & 0xff);
408      b[offset++] = (byte)((iValue >>> 8 ) & 0xff);
409      b[offset++] = (byte)((iValue >>> 16) & 0xff);
410      b[offset++] = (byte)((iValue >>> 24) & 0xff);
411   }
412
413   private static final void PERM_OP(int a, int b, int n, int m, int results[])
414   {
415      int t;
416
417      t = ((a >>> n) ^ b) & m;
418      a ^= t << n;
419      b ^= t;
420
421      results[0] = a;
422      results[1] = b;
423   }
424
425   private static final int HPERM_OP(int a, int n, int m)
426   {
427      int t;
428
429      t = ((a << (16 - n)) ^ a) & m;
430      a = a ^ t ^ (t >>> (16 - n));
431
432      return(a);
433   }
434
435   private static int [] des_set_key(byte key[])
436   {
437      int schedule[] = new int[ITERATIONS * 2];
438
439      int c = fourBytesToInt(key, 0);
440      int d = fourBytesToInt(key, 4);
441
442      int results[] = new int[2];
443
444      PERM_OP(d, c, 4, 0x0f0f0f0f, results);
445      d = results[0]; c = results[1];
446
447      c = HPERM_OP(c, -2, 0xcccc0000);
448      d = HPERM_OP(d, -2, 0xcccc0000);
449
450      PERM_OP(d, c, 1, 0x55555555, results);
451      d = results[0]; c = results[1];
452
453      PERM_OP(c, d, 8, 0x00ff00ff, results);
454      c = results[0]; d = results[1];
455
456      PERM_OP(d, c, 1, 0x55555555, results);
457      d = results[0]; c = results[1];
458
459      d = (((d & 0x000000ff) <<  16) |  (d & 0x0000ff00)     |
460           ((d & 0x00ff0000) >>> 16) | ((c & 0xf0000000) >>> 4));
461      c &= 0x0fffffff;
462
463      int s, t;
464      int j = 0;
465
466      for(int i = 0; i < ITERATIONS; i ++)
467      {
468         if(shifts2[i])
469         {
470            c = (c >>> 2) | (c << 26);
471            d = (d >>> 2) | (d << 26);
472         }
473         else
474         {
475            c = (c >>> 1) | (c << 27);
476            d = (d >>> 1) | (d << 27);
477         }
478
479         c &= 0x0fffffff;
480         d &= 0x0fffffff;
481
482         s = skb[0][ (c       ) & 0x3f                       ]|
483             skb[1][((c >>>  6) & 0x03) | ((c >>>  7) & 0x3c)]|
484             skb[2][((c >>> 13) & 0x0f) | ((c >>> 14) & 0x30)]|
485             skb[3][((c >>> 20) & 0x01) | ((c >>> 21) & 0x06) |
486                                          ((c >>> 22) & 0x38)];
487
488         t = skb[4][ (d     )  & 0x3f                       ]|
489             skb[5][((d >>> 7) & 0x03) | ((d >>>  8) & 0x3c)]|
490             skb[6][ (d >>>15) & 0x3f                       ]|
491             skb[7][((d >>>21) & 0x0f) | ((d >>> 22) & 0x30)];
492
493         schedule[j++] = ((t <<  16) | (s & 0x0000ffff)) & 0xffffffff;
494         s             = ((s >>> 16) | (t & 0xffff0000));
495
496         s             = (s << 4) | (s >>> 28);
497         schedule[j++] = s & 0xffffffff;
498      }
499      return(schedule);
500   }
501
502   private static final int D_ENCRYPT
503   (
504      int L, int R, int S, int E0, int E1, int s[]
505   )
506   {
507      int t, u, v;
508
509      v = R ^ (R >>> 16);
510      u = v & E0;
511      v = v & E1;
512      u = (u ^ (u << 16)) ^ R ^ s[S];
513      t = (v ^ (v << 16)) ^ R ^ s[S + 1];
514      t = (t >>> 4) | (t << 28);
515
516      L ^= SPtrans[1][(t       ) & 0x3f] |
517           SPtrans[3][(t >>>  8) & 0x3f] |
518           SPtrans[5][(t >>> 16) & 0x3f] |
519           SPtrans[7][(t >>> 24) & 0x3f] |
520           SPtrans[0][(u       ) & 0x3f] |
521           SPtrans[2][(u >>>  8) & 0x3f] |
522           SPtrans[4][(u >>> 16) & 0x3f] |
523           SPtrans[6][(u >>> 24) & 0x3f];
524
525      return(L);
526   }
527
528   private static final int [] body(int schedule[], int Eswap0, int Eswap1)
529   {
530      int left = 0;
531      int right = 0;
532      int t     = 0;
533
534      for(int j = 0; j < 25; j ++)
535      {
536         for(int i = 0; i < ITERATIONS * 2; i += 4)
537         {
538            left  = D_ENCRYPT(left,  right, i,     Eswap0, Eswap1, schedule);
539            right = D_ENCRYPT(right, left,  i + 2, Eswap0, Eswap1, schedule);
540         }
541         t     = left; 
542         left  = right; 
543         right = t;
544      }
545
546      t = right;
547
548      right = (left >>> 1) | (left << 31);
549      left  = (t    >>> 1) | (t    << 31);
550
551      left  &= 0xffffffff;
552      right &= 0xffffffff;
553
554      int results[] = new int[2];
555
556      PERM_OP(right, left, 1, 0x55555555, results); 
557      right = results[0]; left = results[1];
558
559      PERM_OP(left, right, 8, 0x00ff00ff, results); 
560      left = results[0]; right = results[1];
561
562      PERM_OP(right, left, 2, 0x33333333, results); 
563      right = results[0]; left = results[1];
564
565      PERM_OP(left, right, 16, 0x0000ffff, results);
566      left = results[0]; right = results[1];
567
568      PERM_OP(right, left, 4, 0x0f0f0f0f, results);
569      right = results[0]; left = results[1];
570
571      int out[] = new int[2];
572
573      out[0] = left; out[1] = right;
574
575      return(out);
576   }
577
578   public static final String crypt(String salt, String original)
579   {
580      while(salt.length() < 2)
581         salt += "A";
582
583      StringBuilder buffer = new StringBuilder("             ");
584
585      char charZero = salt.charAt(0);
586      char charOne  = salt.charAt(1);
587
588      buffer.setCharAt(0, charZero);
589      buffer.setCharAt(1, charOne);
590
591      int Eswap0 = con_salt[charZero];
592      int Eswap1 = con_salt[charOne] << 4;
593 
594      byte key[] = new byte[8];
595
596      for(int i = 0; i < key.length; i ++)
597         key[i] = (byte)0;
598
599      for(int i = 0; i < key.length && i < original.length(); i ++)
600      {
601         int iChar = original.charAt(i);
602
603         key[i] = (byte)(iChar << 1);
604      }
605
606      int schedule[] = des_set_key(key);
607      int out[]      = body(schedule, Eswap0, Eswap1);
608
609      byte b[] = new byte[9];
610
611      intToFourBytes(out[0], b, 0);
612      intToFourBytes(out[1], b, 4);
613      b[8] = 0;
614
615      for(int i = 2, y = 0, u = 0x80; i < 13; i ++)
616      {
617         for(int j = 0, c = 0; j < 6; j ++)
618         {
619            c <<= 1;
620
621            if((b[y] & u) != 0)
622               c |= 1;
623
624            u >>>= 1;
625
626            if(u == 0)
627            {
628               y++;
629               u = 0x80;
630            }
631            buffer.setCharAt(i, (char)cov_2char[c]);
632         }
633      }
634      return(buffer.toString());
635   }
636
637   
638}