View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.codec.digest;
18  
19  import java.nio.charset.StandardCharsets;
20  import java.security.SecureRandom;
21  import java.util.Arrays;
22  import java.util.regex.Pattern;
23  
24  /**
25   * Unix <a href="https://man7.org/linux/man-pages/man3/crypt.3.html">crypt(3)</a> algorithm implementation.
26   * <p>
27   * This class only implements the traditional 56 bit DES based algorithm. Please use Crypt.crypt() for a method
28   * that distinguishes between all the algorithms supported in the current glibc's crypt().
29   * </p>
30   * <p>
31   * The initial Java implementation was taken from the JetSpeed Portal project (see
32   * org.apache.jetspeed.services.security.ldap.UnixCrypt).
33   * </p>
34   * <p>
35   * This class is slightly incompatible if the given salt contains characters that are not part of the allowed range
36   * {@code [a-zA-Z0-9./]}.
37   * </p>
38   * <p>
39   * This class is immutable and thread-safe.
40   * </p>
41   *
42   * @since 1.7
43   */
44  public class UnixCrypt {
45  
46      private static final String CRYPT_SALT_REGEX = "^[" + B64.B64T_STRING + "]{2,}$";
47      private static final Pattern CRYPT_SALT_PATTERN = Pattern.compile(CRYPT_SALT_REGEX);
48  
49      private static final int[] CON_SALT = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 5, 6,
51              7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
52              34, 35, 36, 37, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
53              54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, 0 };
54  
55      private static final int[] COV2CHAR = { 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
56              71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102,
57              103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122 };
58  
59      private static final boolean[] SHIFT2 = { false, false, true, true, true, true, true, true, false, true, true,
60              true, true, true, true, false };
61  
62      private static final int[][] SKB = {
63              { 0, 16, 0x20000000, 0x20000010, 0x10000, 0x10010, 0x20010000, 0x20010010, 2048, 2064, 0x20000800,
64                      0x20000810, 0x10800, 0x10810, 0x20010800, 0x20010810, 32, 48, 0x20000020, 0x20000030, 0x10020,
65                      0x10030, 0x20010020, 0x20010030, 2080, 2096, 0x20000820, 0x20000830, 0x10820, 0x10830, 0x20010820,
66                      0x20010830, 0x80000, 0x80010, 0x20080000, 0x20080010, 0x90000, 0x90010, 0x20090000, 0x20090010,
67                      0x80800, 0x80810, 0x20080800, 0x20080810, 0x90800, 0x90810, 0x20090800, 0x20090810, 0x80020,
68                      0x80030, 0x20080020, 0x20080030, 0x90020, 0x90030, 0x20090020, 0x20090030, 0x80820, 0x80830,
69                      0x20080820, 0x20080830, 0x90820, 0x90830, 0x20090820, 0x20090830 },
70              { 0, 0x2000000, 8192, 0x2002000, 0x200000, 0x2200000, 0x202000, 0x2202000, 4, 0x2000004, 8196, 0x2002004,
71                      0x200004, 0x2200004, 0x202004, 0x2202004, 1024, 0x2000400, 9216, 0x2002400, 0x200400, 0x2200400,
72                      0x202400, 0x2202400, 1028, 0x2000404, 9220, 0x2002404, 0x200404, 0x2200404, 0x202404, 0x2202404,
73                      0x10000000, 0x12000000, 0x10002000, 0x12002000, 0x10200000, 0x12200000, 0x10202000, 0x12202000,
74                      0x10000004, 0x12000004, 0x10002004, 0x12002004, 0x10200004, 0x12200004, 0x10202004, 0x12202004,
75                      0x10000400, 0x12000400, 0x10002400, 0x12002400, 0x10200400, 0x12200400, 0x10202400, 0x12202400,
76                      0x10000404, 0x12000404, 0x10002404, 0x12002404, 0x10200404, 0x12200404, 0x10202404, 0x12202404 },
77              { 0, 1, 0x40000, 0x40001, 0x1000000, 0x1000001, 0x1040000, 0x1040001, 2, 3, 0x40002, 0x40003, 0x1000002,
78                      0x1000003, 0x1040002, 0x1040003, 512, 513, 0x40200, 0x40201, 0x1000200, 0x1000201, 0x1040200,
79                      0x1040201, 514, 515, 0x40202, 0x40203, 0x1000202, 0x1000203, 0x1040202, 0x1040203, 0x8000000,
80                      0x8000001, 0x8040000, 0x8040001, 0x9000000, 0x9000001, 0x9040000, 0x9040001, 0x8000002, 0x8000003,
81                      0x8040002, 0x8040003, 0x9000002, 0x9000003, 0x9040002, 0x9040003, 0x8000200, 0x8000201, 0x8040200,
82                      0x8040201, 0x9000200, 0x9000201, 0x9040200, 0x9040201, 0x8000202, 0x8000203, 0x8040202, 0x8040203,
83                      0x9000202, 0x9000203, 0x9040202, 0x9040203 },
84              { 0, 0x100000, 256, 0x100100, 8, 0x100008, 264, 0x100108, 4096, 0x101000, 4352, 0x101100, 4104, 0x101008,
85                      4360, 0x101108, 0x4000000, 0x4100000, 0x4000100, 0x4100100, 0x4000008, 0x4100008, 0x4000108,
86                      0x4100108, 0x4001000, 0x4101000, 0x4001100, 0x4101100, 0x4001008, 0x4101008, 0x4001108, 0x4101108,
87                      0x20000, 0x120000, 0x20100, 0x120100, 0x20008, 0x120008, 0x20108, 0x120108, 0x21000, 0x121000,
88                      0x21100, 0x121100, 0x21008, 0x121008, 0x21108, 0x121108, 0x4020000, 0x4120000, 0x4020100,
89                      0x4120100, 0x4020008, 0x4120008, 0x4020108, 0x4120108, 0x4021000, 0x4121000, 0x4021100, 0x4121100,
90                      0x4021008, 0x4121008, 0x4021108, 0x4121108 },
91              { 0, 0x10000000, 0x10000, 0x10010000, 4, 0x10000004, 0x10004, 0x10010004, 0x20000000, 0x30000000,
92                      0x20010000, 0x30010000, 0x20000004, 0x30000004, 0x20010004, 0x30010004, 0x100000, 0x10100000,
93                      0x110000, 0x10110000, 0x100004, 0x10100004, 0x110004, 0x10110004, 0x20100000, 0x30100000,
94                      0x20110000, 0x30110000, 0x20100004, 0x30100004, 0x20110004, 0x30110004, 4096, 0x10001000, 0x11000,
95                      0x10011000, 4100, 0x10001004, 0x11004, 0x10011004, 0x20001000, 0x30001000, 0x20011000, 0x30011000,
96                      0x20001004, 0x30001004, 0x20011004, 0x30011004, 0x101000, 0x10101000, 0x111000, 0x10111000,
97                      0x101004, 0x10101004, 0x111004, 0x10111004, 0x20101000, 0x30101000, 0x20111000, 0x30111000,
98                      0x20101004, 0x30101004, 0x20111004, 0x30111004 },
99              { 0, 0x8000000, 8, 0x8000008, 1024, 0x8000400, 1032, 0x8000408, 0x20000, 0x8020000, 0x20008, 0x8020008,
100                     0x20400, 0x8020400, 0x20408, 0x8020408, 1, 0x8000001, 9, 0x8000009, 1025, 0x8000401, 1033,
101                     0x8000409, 0x20001, 0x8020001, 0x20009, 0x8020009, 0x20401, 0x8020401, 0x20409, 0x8020409,
102                     0x2000000, 0xa000000, 0x2000008, 0xa000008, 0x2000400, 0xa000400, 0x2000408, 0xa000408, 0x2020000,
103                     0xa020000, 0x2020008, 0xa020008, 0x2020400, 0xa020400, 0x2020408, 0xa020408, 0x2000001, 0xa000001,
104                     0x2000009, 0xa000009, 0x2000401, 0xa000401, 0x2000409, 0xa000409, 0x2020001, 0xa020001, 0x2020009,
105                     0xa020009, 0x2020401, 0xa020401, 0x2020409, 0xa020409 },
106             { 0, 256, 0x80000, 0x80100, 0x1000000, 0x1000100, 0x1080000, 0x1080100, 16, 272, 0x80010, 0x80110,
107                     0x1000010, 0x1000110, 0x1080010, 0x1080110, 0x200000, 0x200100, 0x280000, 0x280100, 0x1200000,
108                     0x1200100, 0x1280000, 0x1280100, 0x200010, 0x200110, 0x280010, 0x280110, 0x1200010, 0x1200110,
109                     0x1280010, 0x1280110, 512, 768, 0x80200, 0x80300, 0x1000200, 0x1000300, 0x1080200, 0x1080300, 528,
110                     784, 0x80210, 0x80310, 0x1000210, 0x1000310, 0x1080210, 0x1080310, 0x200200, 0x200300, 0x280200,
111                     0x280300, 0x1200200, 0x1200300, 0x1280200, 0x1280300, 0x200210, 0x200310, 0x280210, 0x280310,
112                     0x1200210, 0x1200310, 0x1280210, 0x1280310 },
113             { 0, 0x4000000, 0x40000, 0x4040000, 2, 0x4000002, 0x40002, 0x4040002, 8192, 0x4002000, 0x42000, 0x4042000,
114                     8194, 0x4002002, 0x42002, 0x4042002, 32, 0x4000020, 0x40020, 0x4040020, 34, 0x4000022, 0x40022,
115                     0x4040022, 8224, 0x4002020, 0x42020, 0x4042020, 8226, 0x4002022, 0x42022, 0x4042022, 2048,
116                     0x4000800, 0x40800, 0x4040800, 2050, 0x4000802, 0x40802, 0x4040802, 10240, 0x4002800, 0x42800,
117                     0x4042800, 10242, 0x4002802, 0x42802, 0x4042802, 2080, 0x4000820, 0x40820, 0x4040820, 2082,
118                     0x4000822, 0x40822, 0x4040822, 10272, 0x4002820, 0x42820, 0x4042820, 10274, 0x4002822, 0x42822,
119                     0x4042822 } };
120 
121     private static final int[][] SPTRANS = {
122             { 0x820200, 0x20000, 0x80800000, 0x80820200, 0x800000, 0x80020200, 0x80020000, 0x80800000, 0x80020200,
123                     0x820200, 0x820000, 0x80000200, 0x80800200, 0x800000, 0, 0x80020000, 0x20000, 0x80000000,
124                     0x800200, 0x20200, 0x80820200, 0x820000, 0x80000200, 0x800200, 0x80000000, 512, 0x20200,
125                     0x80820000, 512, 0x80800200, 0x80820000, 0, 0, 0x80820200, 0x800200, 0x80020000, 0x820200,
126                     0x20000, 0x80000200, 0x800200, 0x80820000, 512, 0x20200, 0x80800000, 0x80020200, 0x80000000,
127                     0x80800000, 0x820000, 0x80820200, 0x20200, 0x820000, 0x80800200, 0x800000, 0x80000200, 0x80020000,
128                     0, 0x20000, 0x800000, 0x80800200, 0x820200, 0x80000000, 0x80820000, 512, 0x80020200 },
129             { 0x10042004, 0, 0x42000, 0x10040000, 0x10000004, 8196, 0x10002000, 0x42000, 8192, 0x10040004, 4,
130                     0x10002000, 0x40004, 0x10042000, 0x10040000, 4, 0x40000, 0x10002004, 0x10040004, 8192, 0x42004,
131                     0x10000000, 0, 0x40004, 0x10002004, 0x42004, 0x10042000, 0x10000004, 0x10000000, 0x40000, 8196,
132                     0x10042004, 0x40004, 0x10042000, 0x10002000, 0x42004, 0x10042004, 0x40004, 0x10000004, 0,
133                     0x10000000, 8196, 0x40000, 0x10040004, 8192, 0x10000000, 0x42004, 0x10002004, 0x10042000, 8192, 0,
134                     0x10000004, 4, 0x10042004, 0x42000, 0x10040000, 0x10040004, 0x40000, 8196, 0x10002000, 0x10002004,
135                     4, 0x10040000, 0x42000 },
136             { 0x41000000, 0x1010040, 64, 0x41000040, 0x40010000, 0x1000000, 0x41000040, 0x10040, 0x1000040, 0x10000,
137                     0x1010000, 0x40000000, 0x41010040, 0x40000040, 0x40000000, 0x41010000, 0, 0x40010000, 0x1010040,
138                     64, 0x40000040, 0x41010040, 0x10000, 0x41000000, 0x41010000, 0x1000040, 0x40010040, 0x1010000,
139                     0x10040, 0, 0x1000000, 0x40010040, 0x1010040, 64, 0x40000000, 0x10000, 0x40000040, 0x40010000,
140                     0x1010000, 0x41000040, 0, 0x1010040, 0x10040, 0x41010000, 0x40010000, 0x1000000, 0x41010040,
141                     0x40000000, 0x40010040, 0x41000000, 0x1000000, 0x41010040, 0x10000, 0x1000040, 0x41000040,
142                     0x10040, 0x1000040, 0, 0x41010000, 0x40000040, 0x41000000, 0x40010040, 64, 0x1010000 },
143             { 0x100402, 0x4000400, 2, 0x4100402, 0, 0x4100000, 0x4000402, 0x100002, 0x4100400, 0x4000002, 0x4000000,
144                     1026, 0x4000002, 0x100402, 0x100000, 0x4000000, 0x4100002, 0x100400, 1024, 2, 0x100400, 0x4000402,
145                     0x4100000, 1024, 1026, 0, 0x100002, 0x4100400, 0x4000400, 0x4100002, 0x4100402, 0x100000,
146                     0x4100002, 1026, 0x100000, 0x4000002, 0x100400, 0x4000400, 2, 0x4100000, 0x4000402, 0, 1024,
147                     0x100002, 0, 0x4100002, 0x4100400, 1024, 0x4000000, 0x4100402, 0x100402, 0x100000, 0x4100402, 2,
148                     0x4000400, 0x100402, 0x100002, 0x100400, 0x4100000, 0x4000402, 1026, 0x4000000, 0x4000002,
149                     0x4100400 },
150             { 0x2000000, 16384, 256, 0x2004108, 0x2004008, 0x2000100, 16648, 0x2004000, 16384, 8, 0x2000008, 16640,
151                     0x2000108, 0x2004008, 0x2004100, 0, 16640, 0x2000000, 16392, 264, 0x2000100, 16648, 0, 0x2000008,
152                     8, 0x2000108, 0x2004108, 16392, 0x2004000, 256, 264, 0x2004100, 0x2004100, 0x2000108, 16392,
153                     0x2004000, 16384, 8, 0x2000008, 0x2000100, 0x2000000, 16640, 0x2004108, 0, 16648, 0x2000000, 256,
154                     16392, 0x2000108, 256, 0, 0x2004108, 0x2004008, 0x2004100, 264, 16384, 16640, 0x2004008,
155                     0x2000100, 264, 8, 16648, 0x2004000, 0x2000008 },
156             { 0x20000010, 0x80010, 0, 0x20080800, 0x80010, 2048, 0x20000810, 0x80000, 2064, 0x20080810, 0x80800,
157                     0x20000000, 0x20000800, 0x20000010, 0x20080000, 0x80810, 0x80000, 0x20000810, 0x20080010, 0, 2048,
158                     16, 0x20080800, 0x20080010, 0x20080810, 0x20080000, 0x20000000, 2064, 16, 0x80800, 0x80810,
159                     0x20000800, 2064, 0x20000000, 0x20000800, 0x80810, 0x20080800, 0x80010, 0, 0x20000800, 0x20000000,
160                     2048, 0x20080010, 0x80000, 0x80010, 0x20080810, 0x80800, 16, 0x20080810, 0x80800, 0x80000,
161                     0x20000810, 0x20000010, 0x20080000, 0x80810, 0, 2048, 0x20000010, 0x20000810, 0x20080800,
162                     0x20080000, 2064, 16, 0x20080010 },
163             { 4096, 128, 0x400080, 0x400001, 0x401081, 4097, 4224, 0, 0x400000, 0x400081, 129, 0x401000, 1, 0x401080,
164                     0x401000, 129, 0x400081, 4096, 4097, 0x401081, 0, 0x400080, 0x400001, 4224, 0x401001, 4225,
165                     0x401080, 1, 4225, 0x401001, 128, 0x400000, 4225, 0x401000, 0x401001, 129, 4096, 128, 0x400000,
166                     0x401001, 0x400081, 4225, 4224, 0, 128, 0x400001, 1, 0x400080, 0, 0x400081, 0x400080, 4224, 129,
167                     4096, 0x401081, 0x400000, 0x401080, 1, 4097, 0x401081, 0x400001, 0x401080, 0x401000, 4097 },
168             { 0x8200020, 0x8208000, 32800, 0, 0x8008000, 0x200020, 0x8200000, 0x8208020, 32, 0x8000000, 0x208000,
169                     32800, 0x208020, 0x8008020, 0x8000020, 0x8200000, 32768, 0x208020, 0x200020, 0x8008000, 0x8208020,
170                     0x8000020, 0, 0x208000, 0x8000000, 0x200000, 0x8008020, 0x8200020, 0x200000, 32768, 0x8208000, 32,
171                     0x200000, 32768, 0x8000020, 0x8208020, 32800, 0x8000000, 0, 0x208000, 0x8200020, 0x8008020,
172                     0x8008000, 0x200020, 0x8208000, 32, 0x200020, 0x8008000, 0x8208020, 0x200000, 0x8200000,
173                     0x8000020, 0x208000, 32800, 0x8008020, 0x8200000, 32, 0x8208000, 0x208020, 0, 0x8000000,
174                     0x8200020, 32768, 0x208020 } };
175 
176     private static int[] body(final int[] schedule, final int eSwap0, final int eSwap1) {
177         int left = 0;
178         int right = 0;
179         int t = 0;
180         for (int j = 0; j < 25; j++) {
181             for (int i = 0; i < 32; i += 4) {
182                 left = dEncrypt(left, right, i, eSwap0, eSwap1, schedule);
183                 right = dEncrypt(right, left, i + 2, eSwap0, eSwap1, schedule);
184             }
185             t = left;
186             left = right;
187             right = t;
188         }
189 
190         t = right;
191         right = left >>> 1 | left << 31;
192         left = t >>> 1 | t << 31;
193         final int[] results = new int[2];
194         permOp(right, left, 1, 0x55555555, results);
195         right = results[0];
196         left = results[1];
197         permOp(left, right, 8, 0xff00ff, results);
198         left = results[0];
199         right = results[1];
200         permOp(right, left, 2, 0x33333333, results);
201         right = results[0];
202         left = results[1];
203         permOp(left, right, 16, 65535, results);
204         left = results[0];
205         right = results[1];
206         permOp(right, left, 4, 0xf0f0f0f, results);
207         right = results[0];
208         left = results[1];
209         final int[] out = new int[2];
210         out[0] = left;
211         out[1] = right;
212         return out;
213     }
214 
215     private static int byteToUnsigned(final byte b) {
216         return b & 0xff;
217     }
218 
219     /**
220      * Generates a crypt(3) compatible hash using the DES algorithm.
221      * <p>
222      * A salt is generated for you using {@link SecureRandom}.
223      * </p>
224      *
225      * @param original
226      *            plaintext password
227      * @return a 13 character string starting with the salt string
228      */
229     public static String crypt(final byte[] original) {
230         return crypt(original, null);
231     }
232 
233     /**
234      * Generates a crypt(3) compatible hash using the DES algorithm.
235      * <p>
236      * Using unspecified characters as salt results incompatible hash values.
237      * </p>
238      *
239      * @param original plaintext password
240      * @param salt     a two character string drawn from [a-zA-Z0-9./]. The salt may be null, in which case a salt is generated for you using
241      *                 {@link B64#getRandomSalt(int)}. Only the first two characters are used, others are ignored.
242      * @return a 13 character string starting with the salt string
243      * @throws IllegalArgumentException if the salt does not match the allowed pattern
244      */
245     public static String crypt(final byte[] original, String salt) {
246         if (salt == null) {
247             salt = B64.getRandomSalt(2);
248         } else if (!CRYPT_SALT_PATTERN.matcher(salt).matches()) {
249             throw new IllegalArgumentException("Invalid salt value: " + salt);
250         }
251 
252         final StringBuilder buffer = new StringBuilder("             ");
253         final char charZero = salt.charAt(0);
254         final char charOne = salt.charAt(1);
255         buffer.setCharAt(0, charZero);
256         buffer.setCharAt(1, charOne);
257         final int eSwap0 = CON_SALT[charZero];
258         final int eSwap1 = CON_SALT[charOne] << 4;
259         final byte[] key = new byte[8];
260         Arrays.fill(key, (byte) 0);
261 
262         final int originalLength = original.length;
263         for (int i = 0; i < key.length && i < originalLength; i++) {
264             final int iChar = original[i];
265             key[i] = (byte) (iChar << 1);
266         }
267 
268         final int[] schedule = desSetKey(key);
269         final int[] out = body(schedule, eSwap0, eSwap1);
270         final byte[] b = new byte[9];
271         intToFourBytes(out[0], b, 0);
272         intToFourBytes(out[1], b, 4);
273         b[8] = 0;
274         int i = 2;
275         int y = 0;
276         int u = 128;
277         for (; i < 13; i++) {
278             int j = 0;
279             int c = 0;
280             for (; j < 6; j++) {
281                 c <<= 1;
282                 if ((b[y] & u) != 0) {
283                     c |= 0x1;
284                 }
285                 u >>>= 1;
286                 if (u == 0) {
287                     y++;
288                     u = 128;
289                 }
290                 buffer.setCharAt(i, (char) COV2CHAR[c]);
291             }
292         }
293         return buffer.toString();
294     }
295 
296     /**
297      * Generates a crypt(3) compatible hash using the DES algorithm.
298      * <p>
299      * A salt is generated for you using {@link SecureRandom}.
300      * </p>
301      *
302      * @param original
303      *            plaintext password
304      * @return a 13 character string starting with the salt string
305      */
306     public static String crypt(final String original) {
307         return crypt(original.getBytes(StandardCharsets.UTF_8));
308     }
309 
310     /**
311      * Generates a crypt(3) compatible hash using the DES algorithm.
312      *
313      * @param original
314      *            plaintext password
315      * @param salt
316      *            a two character string drawn from [a-zA-Z0-9./]. The salt may be null, in which case a salt is
317      *            generated for you using {@link SecureRandom}.
318      * @return a 13 character string starting with the salt string
319      * @throws IllegalArgumentException
320      *             if the salt does not match the allowed pattern
321      */
322     public static String crypt(final String original, final String salt) {
323         return crypt(original.getBytes(StandardCharsets.UTF_8), salt);
324     }
325 
326     private static int dEncrypt(int el, final int r, final int s, final int e0, final int e1, final int[] sArr) {
327         int v = r ^ r >>> 16;
328         int u = v & e0;
329         v &= e1;
330         u = u ^ u << 16 ^ r ^ sArr[s];
331         int t = v ^ v << 16 ^ r ^ sArr[s + 1];
332         t = t >>> 4 | t << 28;
333         el ^= SPTRANS[1][t & 0x3f] | SPTRANS[3][t >>> 8 & 0x3f] | SPTRANS[5][t >>> 16 & 0x3f] |
334                 SPTRANS[7][t >>> 24 & 0x3f] | SPTRANS[0][u & 0x3f] | SPTRANS[2][u >>> 8 & 0x3f] |
335                 SPTRANS[4][u >>> 16 & 0x3f] | SPTRANS[6][u >>> 24 & 0x3f];
336         return el;
337     }
338 
339     private static int[] desSetKey(final byte[] key) {
340         final int[] schedule = new int[32];
341         int c = fourBytesToInt(key, 0);
342         int d = fourBytesToInt(key, 4);
343         final int[] results = new int[2];
344         permOp(d, c, 4, 0xf0f0f0f, results);
345         d = results[0];
346         c = results[1];
347         c = hPermOp(c, -2, 0xcccc0000);
348         d = hPermOp(d, -2, 0xcccc0000);
349         permOp(d, c, 1, 0x55555555, results);
350         d = results[0];
351         c = results[1];
352         permOp(c, d, 8, 0xff00ff, results);
353         c = results[0];
354         d = results[1];
355         permOp(d, c, 1, 0x55555555, results);
356         d = results[0];
357         c = results[1];
358         d = (d & 0xff) << 16 | d & 0xff00 | (d & 0xff0000) >>> 16 | (c & 0xf0000000) >>> 4;
359         c &= 0xfffffff;
360         int j = 0;
361         for (int i = 0; i < 16; i++) {
362             if (SHIFT2[i]) {
363                 c = c >>> 2 | c << 26;
364                 d = d >>> 2 | d << 26;
365             } else {
366                 c = c >>> 1 | c << 27;
367                 d = d >>> 1 | d << 27;
368             }
369             c &= 0xfffffff;
370             d &= 0xfffffff;
371             int s = SKB[0][c & 0x3f] | SKB[1][c >>> 6 & 0x3 | c >>> 7 & 0x3c] |
372                     SKB[2][c >>> 13 & 0xf | c >>> 14 & 0x30] |
373                     SKB[3][c >>> 20 & 0x1 | c >>> 21 & 0x6 | c >>> 22 & 0x38];
374             final int t = SKB[4][d & 0x3f] | SKB[5][d >>> 7 & 0x3 | d >>> 8 & 0x3c] | SKB[6][d >>> 15 & 0x3f] |
375                     SKB[7][d >>> 21 & 0xf | d >>> 22 & 0x30];
376             schedule[j++] = t << 16 | s & 0xffff;
377             s = s >>> 16 | t & 0xffff0000;
378             s = s << 4 | s >>> 28;
379             schedule[j++] = s;
380         }
381 
382         return schedule;
383     }
384 
385     private static int fourBytesToInt(final byte[] b, int offset) {
386         int value = byteToUnsigned(b[offset++]);
387         value |= byteToUnsigned(b[offset++]) << 8;
388         value |= byteToUnsigned(b[offset++]) << 16;
389         value |= byteToUnsigned(b[offset++]) << 24;
390         return value;
391     }
392 
393     private static int hPermOp(final int a, final int n, final int m) {
394         final int t = (a << 16 - n ^ a) & m;
395         return a ^ t ^ t >>> 16 - n;
396     }
397 
398     private static void intToFourBytes(final int iValue, final byte[] b, int offset) {
399         b[offset++] = (byte) (iValue & 0xff);
400         b[offset++] = (byte) (iValue >>> 8 & 0xff);
401         b[offset++] = (byte) (iValue >>> 16 & 0xff);
402         b[offset++] = (byte) (iValue >>> 24 & 0xff);
403     }
404 
405     private static void permOp(int a, int b, final int n, final int m, final int[] results) {
406         final int t = (a >>> n ^ b) & m;
407         a ^= t << n;
408         b ^= t;
409         results[0] = a;
410         results[1] = b;
411     }
412 
413     /**
414      * TODO Make private in 2.0.
415      *
416      * @deprecated TODO Make private in 2.0.
417      */
418     @Deprecated
419     public UnixCrypt() {
420         // empty
421     }
422 }