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