View Javadoc

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