Source for gnu.javax.crypto.cipher.DES

   1: /* DES.java --
   2:    Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.javax.crypto.cipher;
  40: 
  41: import gnu.java.security.Registry;
  42: import gnu.java.security.Properties;
  43: import gnu.java.security.util.Util;
  44: 
  45: import java.security.InvalidKeyException;
  46: import java.util.Arrays;
  47: import java.util.Collections;
  48: import java.util.Iterator;
  49: 
  50: /**
  51:  * The Data Encryption Standard. DES is a 64-bit block cipher with a 56-bit
  52:  * key, developed by IBM in the 1970's for the standardization process begun by
  53:  * the National Bureau of Standards (now NIST).
  54:  * <p>
  55:  * New applications should not use DES except for compatibility.
  56:  * <p>
  57:  * This version is based upon the description and sample implementation in
  58:  * [1].
  59:  * <p>
  60:  * References:
  61:  * <ol>
  62:  *    <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms, and
  63:  *    Source Code in C, Second Edition</i>. (1996 John Wiley and Sons) ISBN
  64:  *    0-471-11709-9. Pages 265--301, 623--632.</li>
  65:  * </ol>
  66:  */
  67: public class DES
  68:     extends BaseCipher
  69: {
  70:   /** DES operates on 64 bit blocks. */
  71:   public static final int BLOCK_SIZE = 8;
  72:   /** DES uses 56 bits of a 64 bit parity-adjusted key. */
  73:   public static final int KEY_SIZE = 8;
  74:   // S-Boxes 1 through 8.
  75:   private static final int[] SP1 = new int[] {
  76:       0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404,
  77:       0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400,
  78:       0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
  79:       0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
  80:       0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404,
  81:       0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000,
  82:       0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000,
  83:       0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
  84:       0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404,
  85:       0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000,
  86:       0x00010004, 0x00010400, 0x00000000, 0x01010004 };
  87:   private static final int[] SP2 = new int[] {
  88:       0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020,
  89:       0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000,
  90:       0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
  91:       0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
  92:       0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000,
  93:       0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000,
  94:       0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000,
  95:       0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
  96:       0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020,
  97:       0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020,
  98:       0x80000000, 0x80100020, 0x80108020, 0x00108000 };
  99:   private static final int[] SP3 = new int[] {
 100:       0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000,
 101:       0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000,
 102:       0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
 103:       0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
 104:       0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208,
 105:       0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208,
 106:       0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008,
 107:       0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
 108:       0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208,
 109:       0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000,
 110:       0x00020208, 0x00000008, 0x08020008, 0x00020200 };
 111:   private static final int[] SP4 = new int[] {
 112:       0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081,
 113:       0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081,
 114:       0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
 115:       0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
 116:       0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080,
 117:       0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081,
 118:       0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080,
 119:       0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
 120:       0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001,
 121:       0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001,
 122:       0x00000080, 0x00800000, 0x00002000, 0x00802080 };
 123:   private static final int[] SP5 = new int[] {
 124:       0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100,
 125:       0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100,
 126:       0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
 127:       0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
 128:       0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000,
 129:       0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000,
 130:       0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000,
 131:       0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
 132:       0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000,
 133:       0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000,
 134:       0x00000000, 0x40080000, 0x02080100, 0x40000100 };
 135:   private static final int[] SP6 = new int[] {
 136:       0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010,
 137:       0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010,
 138:       0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
 139:       0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
 140:       0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000,
 141:       0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000,
 142:       0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000,
 143:       0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
 144:       0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000,
 145:       0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000,
 146:       0x20404000, 0x20000000, 0x00400010, 0x20004010 };
 147:   private static final int[] SP7 = new int[] {
 148:       0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802,
 149:       0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002,
 150:       0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
 151:       0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
 152:       0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002,
 153:       0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802,
 154:       0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000,
 155:       0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
 156:       0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000,
 157:       0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800,
 158:       0x04000002, 0x04000800, 0x00000800, 0x00200002 };
 159:   private static final int[] SP8 = new int[] {
 160:       0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040,
 161:       0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000,
 162:       0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
 163:       0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
 164:       0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000,
 165:       0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000,
 166:       0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040,
 167:       0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
 168:       0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000,
 169:       0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040,
 170:       0x00001040, 0x00040040, 0x10000000, 0x10041000 };
 171:   /**
 172:    * Constants that help in determining whether or not a byte array is parity
 173:    * adjusted.
 174:    */
 175:   private static final byte[] PARITY = {
 176:       8, 1, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 2, 8,
 177:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 3,
 178:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 179:       8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
 180:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 181:       8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
 182:       8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
 183:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 184:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 185:       8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
 186:       8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
 187:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 188:       8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
 189:       0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 190:       4, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
 191:       8, 5, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 6, 8 };
 192:   // Key schedule constants.
 193:   private static final byte[] ROTARS = {
 194:       1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
 195:   private static final byte[] PC1 = {
 196:       56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,  9,  1,
 197:       58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35, 62, 54, 46, 38,
 198:       30, 22, 14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 60, 52, 44, 36,
 199:       28, 20, 12,  4, 27, 19, 11,  3 };
 200:   private static final byte[] PC2 = {
 201:       13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9, 22, 18, 11,  3,
 202:       25,  7, 15,  6, 26, 19, 12,  1, 40, 51, 30, 36, 46, 54, 29, 39,
 203:       50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
 204:   /**
 205:    * Weak keys (parity adjusted): If all the bits in each half are either 0
 206:    * or 1, then the key used for any cycle of the algorithm is the same as
 207:    * all other cycles.
 208:    */
 209:   public static final byte[][] WEAK_KEYS = {
 210:       Util.toBytesFromString("0101010101010101"),
 211:       Util.toBytesFromString("01010101FEFEFEFE"),
 212:       Util.toBytesFromString("FEFEFEFE01010101"),
 213:       Util.toBytesFromString("FEFEFEFEFEFEFEFE") };
 214:   /**
 215:    * Semi-weak keys (parity adjusted):  Some pairs of keys encrypt plain text
 216:    * to identical cipher text. In other words, one key in the pair can decrypt
 217:    * messages that were encrypted with the other key. These keys are called
 218:    * semi-weak keys. This occurs because instead of 16 different sub-keys being
 219:    * generated, these semi-weak keys produce only two different sub-keys.
 220:    */
 221:   public static final byte[][] SEMIWEAK_KEYS = {
 222:       Util.toBytesFromString("01FE01FE01FE01FE"),
 223:       Util.toBytesFromString("FE01FE01FE01FE01"),
 224:       Util.toBytesFromString("1FE01FE00EF10EF1"),
 225:       Util.toBytesFromString("E01FE01FF10EF10E"),
 226:       Util.toBytesFromString("01E001E001F101F1"),
 227:       Util.toBytesFromString("E001E001F101F101"),
 228:       Util.toBytesFromString("1FFE1FFE0EFE0EFE"),
 229:       Util.toBytesFromString("FE1FFE1FFE0EFE0E"),
 230:       Util.toBytesFromString("011F011F010E010E"),
 231:       Util.toBytesFromString("1F011F010E010E01"),
 232:       Util.toBytesFromString("E0FEE0FEF1FEF1FE"),
 233:       Util.toBytesFromString("FEE0FEE0FEF1FEF1") };
 234:   /** Possible weak keys (parity adjusted) --produce 4 instead of 16 subkeys. */
 235:   public static final byte[][] POSSIBLE_WEAK_KEYS = {
 236:       Util.toBytesFromString("1F1F01010E0E0101"),
 237:       Util.toBytesFromString("011F1F01010E0E01"),
 238:       Util.toBytesFromString("1F01011F0E01010E"),
 239:       Util.toBytesFromString("01011F1F01010E0E"),
 240:       Util.toBytesFromString("E0E00101F1F10101"),
 241:       Util.toBytesFromString("FEFE0101FEFE0101"),
 242:       Util.toBytesFromString("FEE01F01FEF10E01"),
 243:       Util.toBytesFromString("E0FE1F01F1FE0E01"),
 244:       Util.toBytesFromString("FEE0011FFEF1010E"),
 245:       Util.toBytesFromString("E0FE011FF1FE010E"),
 246:       Util.toBytesFromString("E0E01F1FF1F10E0E"),
 247:       Util.toBytesFromString("FEFE1F1FFEFE0E0E"),
 248:       Util.toBytesFromString("1F1F01010E0E0101"),
 249:       Util.toBytesFromString("011F1F01010E0E01"),
 250:       Util.toBytesFromString("1F01011F0E01010E"),
 251:       Util.toBytesFromString("01011F1F01010E0E"),
 252:       Util.toBytesFromString("01E0E00101F1F101"),
 253:       Util.toBytesFromString("1FFEE0010EFEF001"),
 254:       Util.toBytesFromString("1FE0FE010EF1FE01"),
 255:       Util.toBytesFromString("01FEFE0101FEFE01"),
 256:       Util.toBytesFromString("1FE0E01F0EF1F10E"),
 257:       Util.toBytesFromString("01FEE01F01FEF10E"),
 258:       Util.toBytesFromString("01E0FE1F01F1FE0E"),
 259:       Util.toBytesFromString("1FFEFE1F0EFEFE0E"),
 260: 
 261:       Util.toBytesFromString("E00101E0F10101F1"),
 262:       Util.toBytesFromString("FE1F01E0FE0E0EF1"),
 263:       Util.toBytesFromString("FE011FE0FE010EF1"),
 264:       Util.toBytesFromString("E01F1FE0F10E0EF1"),
 265:       Util.toBytesFromString("FE0101FEFE0101FE"),
 266:       Util.toBytesFromString("E01F01FEF10E01FE"),
 267:       Util.toBytesFromString("E0011FFEF1010EFE"),
 268:       Util.toBytesFromString("FE1F1FFEFE0E0EFE"),
 269:       Util.toBytesFromString("1FFE01E00EFE01F1"),
 270:       Util.toBytesFromString("01FE1FE001FE0EF1"),
 271:       Util.toBytesFromString("1FE001FE0EF101FE"),
 272:       Util.toBytesFromString("01E01FFE01F10EFE"),
 273:       Util.toBytesFromString("0101E0E00101F1F1"),
 274:       Util.toBytesFromString("1F1FE0E00E0EF1F1"),
 275:       Util.toBytesFromString("1F01FEE00E01FEF1"),
 276:       Util.toBytesFromString("011FFEE0010EFEF1"),
 277:       Util.toBytesFromString("1F01E0FE0E01F1FE"),
 278:       Util.toBytesFromString("011FE0FE010EF1FE"),
 279:       Util.toBytesFromString("0101FEFE0001FEFE"),
 280:       Util.toBytesFromString("1F1FFEFE0E0EFEFE"),
 281:       Util.toBytesFromString("FEFEE0E0FEFEF1F1"),
 282:       Util.toBytesFromString("E0FEFEE0F1FEFEF1"),
 283:       Util.toBytesFromString("FEE0E0FEFEF1F1FE"),
 284:       Util.toBytesFromString("E0E0FEFEF1F1FEFE") };
 285: 
 286:   /** Default 0-argument constructor. */
 287:   public DES()
 288:   {
 289:     super(Registry.DES_CIPHER, BLOCK_SIZE, KEY_SIZE);
 290:   }
 291: 
 292:   /**
 293:    * Adjust the parity for a raw key array. This essentially means that each
 294:    * byte in the array will have an odd number of '1' bits (the last bit in
 295:    * each byte is unused.
 296:    *
 297:    * @param kb The key array, to be parity-adjusted.
 298:    * @param offset The starting index into the key bytes.
 299:    */
 300:   public static void adjustParity(byte[] kb, int offset)
 301:   {
 302:     for (int i = offset; i < offset + KEY_SIZE; i++)
 303:       kb[i] ^= (PARITY[kb[i] & 0xff] == 8) ? 1 : 0;
 304:   }
 305: 
 306:   /**
 307:    * Test if a byte array, which must be at least 8 bytes long, is parity
 308:    * adjusted.
 309:    *
 310:    * @param kb The key bytes.
 311:    * @param offset The starting index into the key bytes.
 312:    * @return <code>true</code> if the first 8 bytes of <i>kb</i> have been
 313:    * parity adjusted. <code>false</code> otherwise.
 314:    */
 315:   public static boolean isParityAdjusted(byte[] kb, int offset)
 316:   {
 317:     int w = 0x88888888;
 318:     int n = PARITY[kb[offset + 0] & 0xff];
 319:     n <<= 4;
 320:     n |= PARITY[kb[offset + 1] & 0xff];
 321:     n <<= 4;
 322:     n |= PARITY[kb[offset + 2] & 0xff];
 323:     n <<= 4;
 324:     n |= PARITY[kb[offset + 3] & 0xff];
 325:     n <<= 4;
 326:     n |= PARITY[kb[offset + 4] & 0xff];
 327:     n <<= 4;
 328:     n |= PARITY[kb[offset + 5] & 0xff];
 329:     n <<= 4;
 330:     n |= PARITY[kb[offset + 6] & 0xff];
 331:     n <<= 4;
 332:     n |= PARITY[kb[offset + 7] & 0xff];
 333:     return (n & w) == 0;
 334:   }
 335: 
 336:   /**
 337:    * Test if a key is a weak key.
 338:    *
 339:    * @param kb The key to test.
 340:    * @return <code>true</code> if the key is weak.
 341:    */
 342:   public static boolean isWeak(byte[] kb)
 343:   {
 344:     for (int i = 0; i < WEAK_KEYS.length; i++)
 345:       if (Arrays.equals(WEAK_KEYS[i], kb))
 346:         return true;
 347:     return false;
 348:   }
 349: 
 350:   /**
 351:    * Test if a key is a semi-weak key.
 352:    *
 353:    * @param kb The key to test.
 354:    * @return <code>true</code> if this key is semi-weak.
 355:    */
 356:   public static boolean isSemiWeak(byte[] kb)
 357:   {
 358:     for (int i = 0; i < SEMIWEAK_KEYS.length; i++)
 359:       if (Arrays.equals(SEMIWEAK_KEYS[i], kb))
 360:         return true;
 361:     return false;
 362:   }
 363: 
 364:   /**
 365:    * Test if the designated byte array represents a possibly weak key.
 366:    *
 367:    * @param kb the byte array to test.
 368:    * @return <code>true</code> if <code>kb</code>represents a possibly weak key.
 369:    * Returns <code>false</code> otherwise.
 370:    */
 371:   public static boolean isPossibleWeak(byte[] kb)
 372:   {
 373:     for (int i = 0; i < POSSIBLE_WEAK_KEYS.length; i++)
 374:       if (Arrays.equals(POSSIBLE_WEAK_KEYS[i], kb))
 375:         return true;
 376:     return false;
 377:   }
 378: 
 379:   /**
 380:    * The core DES function. This is used for both encryption and decryption,
 381:    * the only difference being the key.
 382:    *
 383:    * @param in The input bytes.
 384:    * @param i The starting offset into the input bytes.
 385:    * @param out The output bytes.
 386:    * @param o The starting offset into the output bytes.
 387:    * @param key The working key.
 388:    */
 389:   private static void desFunc(byte[] in, int i, byte[] out, int o, int[] key)
 390:   {
 391:     int right, left, work;
 392:     // Load.
 393:     left =  (in[i++] & 0xff) << 24
 394:           | (in[i++] & 0xff) << 16
 395:           | (in[i++] & 0xff) << 8
 396:           |  in[i++] & 0xff;
 397:     right = (in[i++] & 0xff) << 24
 398:           | (in[i++] & 0xff) << 16
 399:           | (in[i++] & 0xff) << 8
 400:           |  in[i  ] & 0xff;
 401:     // Initial permutation.
 402:     work = ((left >>> 4) ^ right) & 0x0F0F0F0F;
 403:     left ^= work << 4;
 404:     right ^= work;
 405: 
 406:     work = ((left >>> 16) ^ right) & 0x0000FFFF;
 407:     left ^= work << 16;
 408:     right ^= work;
 409: 
 410:     work = ((right >>> 2) ^ left) & 0x33333333;
 411:     right ^= work << 2;
 412:     left ^= work;
 413: 
 414:     work = ((right >>> 8) ^ left) & 0x00FF00FF;
 415:     right ^= work << 8;
 416:     left ^= work;
 417: 
 418:     right = ((right << 1) | ((right >>> 31) & 1)) & 0xFFFFFFFF;
 419:     work = (left ^ right) & 0xAAAAAAAA;
 420:     left ^= work;
 421:     right ^= work;
 422:     left = ((left << 1) | ((left >>> 31) & 1)) & 0xFFFFFFFF;
 423: 
 424:     int k = 0, t;
 425:     for (int round = 0; round < 8; round++)
 426:       {
 427:         work = right >>> 4 | right << 28;
 428:         work ^= key[k++];
 429:         t = SP7[work & 0x3F];
 430:         work >>>= 8;
 431:         t |= SP5[work & 0x3F];
 432:         work >>>= 8;
 433:         t |= SP3[work & 0x3F];
 434:         work >>>= 8;
 435:         t |= SP1[work & 0x3F];
 436:         work = right ^ key[k++];
 437:         t |= SP8[work & 0x3F];
 438:         work >>>= 8;
 439:         t |= SP6[work & 0x3F];
 440:         work >>>= 8;
 441:         t |= SP4[work & 0x3F];
 442:         work >>>= 8;
 443:         t |= SP2[work & 0x3F];
 444:         left ^= t;
 445: 
 446:         work = left >>> 4 | left << 28;
 447:         work ^= key[k++];
 448:         t = SP7[work & 0x3F];
 449:         work >>>= 8;
 450:         t |= SP5[work & 0x3F];
 451:         work >>>= 8;
 452:         t |= SP3[work & 0x3F];
 453:         work >>>= 8;
 454:         t |= SP1[work & 0x3F];
 455:         work = left ^ key[k++];
 456:         t |= SP8[work & 0x3F];
 457:         work >>>= 8;
 458:         t |= SP6[work & 0x3F];
 459:         work >>>= 8;
 460:         t |= SP4[work & 0x3F];
 461:         work >>>= 8;
 462:         t |= SP2[work & 0x3F];
 463:         right ^= t;
 464:       }
 465:     // The final permutation.
 466:     right = (right << 31) | (right >>> 1);
 467:     work = (left ^ right) & 0xAAAAAAAA;
 468:     left ^= work;
 469:     right ^= work;
 470:     left = (left << 31) | (left >>> 1);
 471: 
 472:     work = ((left >>> 8) ^ right) & 0x00FF00FF;
 473:     left ^= work << 8;
 474:     right ^= work;
 475: 
 476:     work = ((left >>> 2) ^ right) & 0x33333333;
 477:     left ^= work << 2;
 478:     right ^= work;
 479: 
 480:     work = ((right >>> 16) ^ left) & 0x0000FFFF;
 481:     right ^= work << 16;
 482:     left ^= work;
 483: 
 484:     work = ((right >>> 4) ^ left) & 0x0F0F0F0F;
 485:     right ^= work << 4;
 486:     left ^= work;
 487: 
 488:     out[o++] = (byte)(right >>> 24);
 489:     out[o++] = (byte)(right >>> 16);
 490:     out[o++] = (byte)(right >>> 8);
 491:     out[o++] = (byte) right;
 492:     out[o++] = (byte)(left >>> 24);
 493:     out[o++] = (byte)(left >>> 16);
 494:     out[o++] = (byte)(left >>> 8);
 495:     out[o  ] = (byte) left;
 496:   }
 497: 
 498:   public Object clone()
 499:   {
 500:     return new DES();
 501:   }
 502: 
 503:   public Iterator blockSizes()
 504:   {
 505:     return Collections.singleton(Integer.valueOf(BLOCK_SIZE)).iterator();
 506:   }
 507: 
 508:   public Iterator keySizes()
 509:   {
 510:     return Collections.singleton(Integer.valueOf(KEY_SIZE)).iterator();
 511:   }
 512: 
 513:   public Object makeKey(byte[] kb, int bs) throws InvalidKeyException
 514:   {
 515:     if (kb == null || kb.length != KEY_SIZE)
 516:       throw new InvalidKeyException("DES keys must be 8 bytes long");
 517: 
 518:     if (Properties.checkForWeakKeys()
 519:         && (isWeak(kb) || isSemiWeak(kb) || isPossibleWeak(kb)))
 520:       throw new WeakKeyException();
 521: 
 522:     int i, j, l, m, n;
 523:     long pc1m = 0, pcr = 0;
 524: 
 525:     for (i = 0; i < 56; i++)
 526:       {
 527:         l = PC1[i];
 528:         pc1m |= ((kb[l >>> 3] & (0x80 >>> (l & 7))) != 0) ? (1L << (55 - i))
 529:                                                           : 0;
 530:       }
 531:     Context ctx = new Context();
 532:     // Encryption key first.
 533:     for (i = 0; i < 16; i++)
 534:       {
 535:         pcr = 0;
 536:         m = i << 1;
 537:         n = m + 1;
 538:         for (j = 0; j < 28; j++)
 539:           {
 540:             l = j + ROTARS[i];
 541:             if (l < 28)
 542:               pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0;
 543:             else
 544:               pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j))
 545:                                                            : 0;
 546:           }
 547:         for (j = 28; j < 56; j++)
 548:           {
 549:             l = j + ROTARS[i];
 550:             if (l < 56)
 551:               pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0;
 552:             else
 553:               pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j))
 554:                                                            : 0;
 555:           }
 556:         for (j = 0; j < 24; j++)
 557:           {
 558:             if ((pcr & 1L << (55 - PC2[j])) != 0)
 559:               ctx.ek[m] |= 1 << (23 - j);
 560:             if ((pcr & 1L << (55 - PC2[j + 24])) != 0)
 561:               ctx.ek[n] |= 1 << (23 - j);
 562:           }
 563:       }
 564:     // The decryption key is the same, but in reversed order.
 565:     for (i = 0; i < Context.EXPANDED_KEY_SIZE; i += 2)
 566:       {
 567:         ctx.dk[30 - i] = ctx.ek[i];
 568:         ctx.dk[31 - i] = ctx.ek[i + 1];
 569:       }
 570:     // "Cook" the keys.
 571:     for (i = 0; i < 32; i += 2)
 572:       {
 573:         int x, y;
 574:         x = ctx.ek[i];
 575:         y = ctx.ek[i + 1];
 576:         ctx.ek[i    ] = ((x & 0x00FC0000)  <<  6)
 577:                       | ((x & 0x00000FC0)  << 10)
 578:                       | ((y & 0x00FC0000) >>> 10)
 579:                       | ((y & 0x00000FC0) >>>  6);
 580:         ctx.ek[i + 1] = ((x & 0x0003F000)  << 12)
 581:                       | ((x & 0x0000003F)  << 16)
 582:                       | ((y & 0x0003F000) >>>  4)
 583:                       |  (y & 0x0000003F);
 584:         x = ctx.dk[i];
 585:         y = ctx.dk[i + 1];
 586:         ctx.dk[i    ] = ((x & 0x00FC0000)  <<  6)
 587:                       | ((x & 0x00000FC0)  << 10)
 588:                       | ((y & 0x00FC0000) >>> 10)
 589:                       | ((y & 0x00000FC0) >>>  6);
 590:         ctx.dk[i + 1] = ((x & 0x0003F000)  << 12)
 591:                       | ((x & 0x0000003F)  << 16)
 592:                       | ((y & 0x0003F000) >>>  4)
 593:                       |  (y & 0x0000003F);
 594:       }
 595:     return ctx;
 596:   }
 597: 
 598:   public void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
 599:   {
 600:     desFunc(in, i, out, o, ((Context) K).ek);
 601:   }
 602: 
 603:   public void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
 604:   {
 605:     desFunc(in, i, out, o, ((Context) K).dk);
 606:   }
 607: 
 608:   /**
 609:    * Simple wrapper class around the session keys. Package-private so TripleDES
 610:    * can see it.
 611:    */
 612:   final class Context
 613:   {
 614:     private static final int EXPANDED_KEY_SIZE = 32;
 615: 
 616:     /** The encryption key. */
 617:     int[] ek;
 618: 
 619:     /** The decryption key. */
 620:     int[] dk;
 621: 
 622:     /** Default 0-arguments constructor. */
 623:     Context()
 624:     {
 625:       ek = new int[EXPANDED_KEY_SIZE];
 626:       dk = new int[EXPANDED_KEY_SIZE];
 627:     }
 628: 
 629:     byte[] getEncryptionKeyBytes()
 630:     {
 631:       return toByteArray(ek);
 632:     }
 633: 
 634:     byte[] getDecryptionKeyBytes()
 635:     {
 636:       return toByteArray(dk);
 637:     }
 638: 
 639:     byte[] toByteArray(int[] k)
 640:     {
 641:       byte[] result = new byte[4 * k.length];
 642:       for (int i = 0, j = 0; i < k.length; i++)
 643:         {
 644:           result[j++] = (byte)(k[i] >>> 24);
 645:           result[j++] = (byte)(k[i] >>> 16);
 646:           result[j++] = (byte)(k[i] >>> 8);
 647:           result[j++] = (byte) k[i];
 648:         }
 649:       return result;
 650:     }
 651:   }
 652: }