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