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