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.util.Random; 020 021import org.apache.commons.codec.Charsets; 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 * @version $Id: UnixCrypt.java 1429868 2013-01-07 16:08:05Z ggregory $ 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 * As no salt is given, a random one will be used. 176 * 177 * @param original 178 * plaintext password 179 * @return a 13 character string starting with the salt string 180 */ 181 public static String crypt(final byte[] original) { 182 return crypt(original, null); 183 } 184 185 /** 186 * Generates a crypt(3) compatible hash using the DES algorithm. 187 * <p> 188 * Using unspecified characters as salt results incompatible hash values. 189 * 190 * @param original 191 * plaintext password 192 * @param salt 193 * a two character string drawn from [a-zA-Z0-9./] or null for a random one 194 * @return a 13 character string starting with the salt string 195 * @throws IllegalArgumentException 196 * if the salt does not match the allowed pattern 197 */ 198 public static String crypt(final byte[] original, String salt) { 199 if (salt == null) { 200 final Random randomGenerator = new Random(); 201 final int numSaltChars = SALT_CHARS.length; 202 salt = "" + SALT_CHARS[randomGenerator.nextInt(numSaltChars)] + 203 SALT_CHARS[randomGenerator.nextInt(numSaltChars)]; 204 } else if (!salt.matches("^[" + B64.B64T + "]{2,}$")) { 205 throw new IllegalArgumentException("Invalid salt value: " + salt); 206 } 207 208 final StringBuilder buffer = new StringBuilder(" "); 209 final char charZero = salt.charAt(0); 210 final char charOne = salt.charAt(1); 211 buffer.setCharAt(0, charZero); 212 buffer.setCharAt(1, charOne); 213 final int eSwap0 = CON_SALT[charZero]; 214 final int eSwap1 = CON_SALT[charOne] << 4; 215 final byte key[] = new byte[8]; 216 for (int i = 0; i < key.length; i++) { 217 key[i] = 0; 218 } 219 220 for (int i = 0; i < key.length && i < original.length; i++) { 221 final int iChar = original[i]; 222 key[i] = (byte) (iChar << 1); 223 } 224 225 final int schedule[] = desSetKey(key); 226 final int out[] = body(schedule, eSwap0, eSwap1); 227 final byte b[] = new byte[9]; 228 intToFourBytes(out[0], b, 0); 229 intToFourBytes(out[1], b, 4); 230 b[8] = 0; 231 int i = 2; 232 int y = 0; 233 int u = 128; 234 for (; i < 13; i++) { 235 int j = 0; 236 int c = 0; 237 for (; j < 6; j++) { 238 c <<= 1; 239 if ((b[y] & u) != 0) { 240 c |= 0x1; 241 } 242 u >>>= 1; 243 if (u == 0) { 244 y++; 245 u = 128; 246 } 247 buffer.setCharAt(i, (char) COV2CHAR[c]); 248 } 249 } 250 return buffer.toString(); 251 } 252 253 /** 254 * Generates a crypt(3) compatible hash using the DES algorithm. 255 * <p> 256 * As no salt is given, a random one is used. 257 * 258 * @param original 259 * plaintext password 260 * @return a 13 character string starting with the salt string 261 */ 262 public static String crypt(final String original) { 263 return crypt(original.getBytes(Charsets.UTF_8)); 264 } 265 266 /** 267 * Generates a crypt(3) compatible hash using the DES algorithm. 268 * 269 * @param original 270 * plaintext password 271 * @param salt 272 * a two character string drawn from [a-zA-Z0-9./] or null for a random one 273 * @return a 13 character string starting with the salt string 274 * @throws IllegalArgumentException 275 * if the salt does not match the allowed pattern 276 */ 277 public static String crypt(final String original, final String salt) { 278 return crypt(original.getBytes(Charsets.UTF_8), salt); 279 } 280 281 private static int[] body(final int schedule[], final int eSwap0, final int eSwap1) { 282 int left = 0; 283 int right = 0; 284 int t = 0; 285 for (int j = 0; j < 25; j++) { 286 for (int i = 0; i < 32; i += 4) { 287 left = dEncrypt(left, right, i, eSwap0, eSwap1, schedule); 288 right = dEncrypt(right, left, i + 2, eSwap0, eSwap1, schedule); 289 } 290 t = left; 291 left = right; 292 right = t; 293 } 294 295 t = right; 296 right = left >>> 1 | left << 31; 297 left = t >>> 1 | t << 31; 298 final int results[] = new int[2]; 299 permOp(right, left, 1, 0x55555555, results); 300 right = results[0]; 301 left = results[1]; 302 permOp(left, right, 8, 0xff00ff, results); 303 left = results[0]; 304 right = results[1]; 305 permOp(right, left, 2, 0x33333333, results); 306 right = results[0]; 307 left = results[1]; 308 permOp(left, right, 16, 65535, results); 309 left = results[0]; 310 right = results[1]; 311 permOp(right, left, 4, 0xf0f0f0f, results); 312 right = results[0]; 313 left = results[1]; 314 final int out[] = new int[2]; 315 out[0] = left; 316 out[1] = right; 317 return out; 318 } 319 320 private static int byteToUnsigned(final byte b) { 321 final int value = b; 322 return value < 0 ? value + 256 : value; 323 } 324 325 private static int dEncrypt(int el, final int r, final int s, final int e0, final int e1, final int sArr[]) { 326 int v = r ^ r >>> 16; 327 int u = v & e0; 328 v &= e1; 329 u = u ^ u << 16 ^ r ^ sArr[s]; 330 int t = v ^ v << 16 ^ r ^ sArr[s + 1]; 331 t = t >>> 4 | t << 28; 332 el ^= SPTRANS[1][t & 0x3f] | SPTRANS[3][t >>> 8 & 0x3f] | SPTRANS[5][t >>> 16 & 0x3f] | 333 SPTRANS[7][t >>> 24 & 0x3f] | SPTRANS[0][u & 0x3f] | SPTRANS[2][u >>> 8 & 0x3f] | 334 SPTRANS[4][u >>> 16 & 0x3f] | SPTRANS[6][u >>> 24 & 0x3f]; 335 return el; 336 } 337 338 private static int[] desSetKey(final byte key[]) { 339 final int schedule[] = new int[32]; 340 int c = fourBytesToInt(key, 0); 341 int d = fourBytesToInt(key, 4); 342 final int results[] = new int[2]; 343 permOp(d, c, 4, 0xf0f0f0f, results); 344 d = results[0]; 345 c = results[1]; 346 c = hPermOp(c, -2, 0xcccc0000); 347 d = hPermOp(d, -2, 0xcccc0000); 348 permOp(d, c, 1, 0x55555555, results); 349 d = results[0]; 350 c = results[1]; 351 permOp(c, d, 8, 0xff00ff, results); 352 c = results[0]; 353 d = results[1]; 354 permOp(d, c, 1, 0x55555555, results); 355 d = results[0]; 356 c = results[1]; 357 d = (d & 0xff) << 16 | d & 0xff00 | (d & 0xff0000) >>> 16 | (c & 0xf0000000) >>> 4; 358 c &= 0xfffffff; 359 int j = 0; 360 for (int i = 0; i < 16; i++) { 361 if (SHIFT2[i]) { 362 c = c >>> 2 | c << 26; 363 d = d >>> 2 | d << 26; 364 } else { 365 c = c >>> 1 | c << 27; 366 d = d >>> 1 | d << 27; 367 } 368 c &= 0xfffffff; 369 d &= 0xfffffff; 370 int s = SKB[0][c & 0x3f] | SKB[1][c >>> 6 & 0x3 | c >>> 7 & 0x3c] | 371 SKB[2][c >>> 13 & 0xf | c >>> 14 & 0x30] | 372 SKB[3][c >>> 20 & 0x1 | c >>> 21 & 0x6 | c >>> 22 & 0x38]; 373 final int t = SKB[4][d & 0x3f] | SKB[5][d >>> 7 & 0x3 | d >>> 8 & 0x3c] | SKB[6][d >>> 15 & 0x3f] | 374 SKB[7][d >>> 21 & 0xf | d >>> 22 & 0x30]; 375 schedule[j++] = (t << 16 | s & 0xffff); 376 s = s >>> 16 | t & 0xffff0000; 377 s = s << 4 | s >>> 28; 378 schedule[j++] = s; 379 } 380 381 return schedule; 382 } 383 384 private static int fourBytesToInt(final byte b[], int offset) { 385 int value = byteToUnsigned(b[offset++]); 386 value |= byteToUnsigned(b[offset++]) << 8; 387 value |= byteToUnsigned(b[offset++]) << 16; 388 value |= byteToUnsigned(b[offset++]) << 24; 389 return value; 390 } 391 392 private static int hPermOp(int a, final int n, final int m) { 393 final int t = (a << 16 - n ^ a) & m; 394 a = a ^ t ^ t >>> 16 - n; 395 return a; 396 } 397 398 private static void intToFourBytes(final int iValue, final byte b[], int offset) { 399 b[offset++] = (byte) (iValue & 0xff); 400 b[offset++] = (byte) (iValue >>> 8 & 0xff); 401 b[offset++] = (byte) (iValue >>> 16 & 0xff); 402 b[offset++] = (byte) (iValue >>> 24 & 0xff); 403 } 404 405 private static void permOp(int a, int b, final int n, final int m, final int results[]) { 406 final int t = (a >>> n ^ b) & m; 407 a ^= t << n; 408 b ^= t; 409 results[0] = a; 410 results[1] = b; 411 } 412 413}