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