View Javadoc

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