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