001    package org.apache.fulcrum.crypto.impl;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.Random;
023    
024    /**
025     * Unix crypt (3) algorithm implementation. The java
026     * implementation was taken from the JetSpeed Portal project
027     * (see org.apache.jetspeed.services.security.ldap.UnixCrypt).
028     *
029     * @author Siegfried Goeschl
030     */
031    public class UnixCrypt
032    {
033        private static final char saltChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./".toCharArray();
034        private static final int ITERATIONS = 16;
035        private static final int con_salt[] = {
036            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
037            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
038            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
039            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
040            0, 0, 0, 0, 0, 0, 0, 1, 2, 3,
041            4, 5, 6, 7, 8, 9, 10, 11, 5, 6,
042            7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
043            17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
044            27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
045            37, 32, 33, 34, 35, 36, 37, 38, 39, 40,
046            41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
047            51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
048            61, 62, 63, 0, 0, 0, 0, 0
049        };
050        private static final boolean shifts2[] = {
051            false, false, true, true, true, true, true, true, false, true,
052            true, true, true, true, true, false
053        };
054        private static final int skb[][] = {
055            {
056                0, 16, 0x20000000, 0x20000010, 0x10000, 0x10010, 0x20010000, 0x20010010, 2048, 2064,
057                0x20000800, 0x20000810, 0x10800, 0x10810, 0x20010800, 0x20010810, 32, 48, 0x20000020, 0x20000030,
058                0x10020, 0x10030, 0x20010020, 0x20010030, 2080, 2096, 0x20000820, 0x20000830, 0x10820, 0x10830,
059                0x20010820, 0x20010830, 0x80000, 0x80010, 0x20080000, 0x20080010, 0x90000, 0x90010, 0x20090000, 0x20090010,
060                0x80800, 0x80810, 0x20080800, 0x20080810, 0x90800, 0x90810, 0x20090800, 0x20090810, 0x80020, 0x80030,
061                0x20080020, 0x20080030, 0x90020, 0x90030, 0x20090020, 0x20090030, 0x80820, 0x80830, 0x20080820, 0x20080830,
062                0x90820, 0x90830, 0x20090820, 0x20090830
063            }, {
064                0, 0x2000000, 8192, 0x2002000, 0x200000, 0x2200000, 0x202000, 0x2202000, 4, 0x2000004,
065                8196, 0x2002004, 0x200004, 0x2200004, 0x202004, 0x2202004, 1024, 0x2000400, 9216, 0x2002400,
066                0x200400, 0x2200400, 0x202400, 0x2202400, 1028, 0x2000404, 9220, 0x2002404, 0x200404, 0x2200404,
067                0x202404, 0x2202404, 0x10000000, 0x12000000, 0x10002000, 0x12002000, 0x10200000, 0x12200000, 0x10202000, 0x12202000,
068                0x10000004, 0x12000004, 0x10002004, 0x12002004, 0x10200004, 0x12200004, 0x10202004, 0x12202004, 0x10000400, 0x12000400,
069                0x10002400, 0x12002400, 0x10200400, 0x12200400, 0x10202400, 0x12202400, 0x10000404, 0x12000404, 0x10002404, 0x12002404,
070                0x10200404, 0x12200404, 0x10202404, 0x12202404
071            }, {
072                0, 1, 0x40000, 0x40001, 0x1000000, 0x1000001, 0x1040000, 0x1040001, 2, 3,
073                0x40002, 0x40003, 0x1000002, 0x1000003, 0x1040002, 0x1040003, 512, 513, 0x40200, 0x40201,
074                0x1000200, 0x1000201, 0x1040200, 0x1040201, 514, 515, 0x40202, 0x40203, 0x1000202, 0x1000203,
075                0x1040202, 0x1040203, 0x8000000, 0x8000001, 0x8040000, 0x8040001, 0x9000000, 0x9000001, 0x9040000, 0x9040001,
076                0x8000002, 0x8000003, 0x8040002, 0x8040003, 0x9000002, 0x9000003, 0x9040002, 0x9040003, 0x8000200, 0x8000201,
077                0x8040200, 0x8040201, 0x9000200, 0x9000201, 0x9040200, 0x9040201, 0x8000202, 0x8000203, 0x8040202, 0x8040203,
078                0x9000202, 0x9000203, 0x9040202, 0x9040203
079            }, {
080                0, 0x100000, 256, 0x100100, 8, 0x100008, 264, 0x100108, 4096, 0x101000,
081                4352, 0x101100, 4104, 0x101008, 4360, 0x101108, 0x4000000, 0x4100000, 0x4000100, 0x4100100,
082                0x4000008, 0x4100008, 0x4000108, 0x4100108, 0x4001000, 0x4101000, 0x4001100, 0x4101100, 0x4001008, 0x4101008,
083                0x4001108, 0x4101108, 0x20000, 0x120000, 0x20100, 0x120100, 0x20008, 0x120008, 0x20108, 0x120108,
084                0x21000, 0x121000, 0x21100, 0x121100, 0x21008, 0x121008, 0x21108, 0x121108, 0x4020000, 0x4120000,
085                0x4020100, 0x4120100, 0x4020008, 0x4120008, 0x4020108, 0x4120108, 0x4021000, 0x4121000, 0x4021100, 0x4121100,
086                0x4021008, 0x4121008, 0x4021108, 0x4121108
087            }, {
088                0, 0x10000000, 0x10000, 0x10010000, 4, 0x10000004, 0x10004, 0x10010004, 0x20000000, 0x30000000,
089                0x20010000, 0x30010000, 0x20000004, 0x30000004, 0x20010004, 0x30010004, 0x100000, 0x10100000, 0x110000, 0x10110000,
090                0x100004, 0x10100004, 0x110004, 0x10110004, 0x20100000, 0x30100000, 0x20110000, 0x30110000, 0x20100004, 0x30100004,
091                0x20110004, 0x30110004, 4096, 0x10001000, 0x11000, 0x10011000, 4100, 0x10001004, 0x11004, 0x10011004,
092                0x20001000, 0x30001000, 0x20011000, 0x30011000, 0x20001004, 0x30001004, 0x20011004, 0x30011004, 0x101000, 0x10101000,
093                0x111000, 0x10111000, 0x101004, 0x10101004, 0x111004, 0x10111004, 0x20101000, 0x30101000, 0x20111000, 0x30111000,
094                0x20101004, 0x30101004, 0x20111004, 0x30111004
095            }, {
096                0, 0x8000000, 8, 0x8000008, 1024, 0x8000400, 1032, 0x8000408, 0x20000, 0x8020000,
097                0x20008, 0x8020008, 0x20400, 0x8020400, 0x20408, 0x8020408, 1, 0x8000001, 9, 0x8000009,
098                1025, 0x8000401, 1033, 0x8000409, 0x20001, 0x8020001, 0x20009, 0x8020009, 0x20401, 0x8020401,
099                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    }