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