Frames | No Frames |
1: /* TripleDES.java -- 2: Copyright (C) 2002, 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: 43: import java.util.ArrayList; 44: import java.util.Collections; 45: import java.util.Iterator; 46: import java.security.InvalidKeyException; 47: 48: /** 49: * Triple-DES, 3DES, or DESede is a <i>combined cipher</i> that uses three 50: * iterations of the Data Encryption Standard cipher to theoretically improve 51: * the security of plain DES, at the cost of speed. 52: * <p> 53: * Triple-DES runs the DES algorithm three times with one, two or three 54: * independent 56-bit (DES) keys. When used with one DES key, the cipher behaves 55: * exactly like a (slower) DES. 56: * <p> 57: * To encrypt: 58: * <blockquote><i>C<sub>i</sub> = E<sub>k3</sub> ( E<sub>k2</sub><sup>-1</sup> ( 59: * E<sub>k1</sub> ( P<sub>i</sub> )))</i> 60: * </blockquote> 61: * <p> 62: * And to decrypt: 63: * <blockquote><i>P<sub>i</sub> = E<sub>k1</sub><sup>-1</sup> ( 64: * E<sub>k2</sub> ( E<sub>k3</sub><sup>-1</sup> ( C<sub>i</sub> )))</i> 65: * </blockquote> 66: * <p> 67: * (The "ede" comes from the encryption operation, which runs 68: * Encrypt-Decrypt-Encrypt) 69: * <p> 70: * References: 71: * <ol> 72: * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms, and 73: * Source Code in C, Second Edition</i>. (1996 John Wiley and Sons) ISBN 74: * 0-471-11709-9. Page 294--295.</li> 75: * </ol> 76: */ 77: public class TripleDES 78: extends BaseCipher 79: { 80: /** Triple-DES only operates on 64 bit blocks. */ 81: public static final int BLOCK_SIZE = 8; 82: /** By default, Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */ 83: public static final int KEY_SIZE = 24; 84: /** The underlying DES instance. */ 85: private DES des; 86: 87: /** 88: * Default 0-arguments constructor. 89: */ 90: public TripleDES() 91: { 92: super(Registry.TRIPLEDES_CIPHER, BLOCK_SIZE, KEY_SIZE); 93: des = new DES(); 94: } 95: 96: /** 97: * Convenience method which calls the method with same name and three 98: * arguments, passing <code>3</code> as the value of the first parameter. 99: * 100: * @param kb The key bytes to adjust. 101: * @param offset The starting offset into the key bytes. 102: */ 103: public static void adjustParity(byte[] kb, int offset) 104: { 105: adjustParity(3, kb, offset); 106: } 107: 108: /** 109: * Adjusts, in-situ, the parity of the designated bytes, so they can be used 110: * as DES keys for a 3-DES 1-, 2- or 3-key cipher. 111: * 112: * @param keyCount the number of independent DES keys. Can be either 113: * <code>1</code>, <code>2</code> or <code>3</code>. Any other value 114: * will cause an {@link IllegalArgumentException} to be raised. 115: * @param kb the array containing the key bytes to adjust. MUST have at least 116: * <code>8 * keyCount</code> bytes starting at offset position 117: * <code>offset</code>, otherwise an 118: * {@link ArrayIndexOutOfBoundsException} will be raised. 119: * @param offset the starting offset into the array. 120: * @see DES#adjustParity(byte[],int) 121: */ 122: public static void adjustParity(int keyCount, byte[] kb, int offset) 123: { 124: if (keyCount < 1 || keyCount > 3) 125: throw new IllegalArgumentException("Invalid keyCount value: " + keyCount); 126: DES.adjustParity(kb, offset); 127: if (keyCount > 1) 128: DES.adjustParity(kb, offset + 8); 129: if (keyCount > 2) 130: DES.adjustParity(kb, offset + 16); 131: } 132: 133: /** 134: * Convenience method which calls the method with same name and three 135: * arguments, passing <code>3</code> as the value of the first parameter. 136: * 137: * @param kb The key bytes to test. 138: * @param offset The starting offset into the key bytes. 139: * @return <code>true</code> if the bytes in <i>kb</i> starting at 140: * <i>offset</i> are parity adjusted. 141: * @see DES#isParityAdjusted(byte[],int) 142: * @see #adjustParity(byte[],int) 143: */ 144: public static boolean isParityAdjusted(byte[] kb, int offset) 145: { 146: return isParityAdjusted(3, kb, offset); 147: } 148: 149: /** 150: * Tests if enough bytes, expected to be used as DES keys for a 3-DES 1-, 2- 151: * or 3-key cipher, located in a designated byte array, has already been 152: * parity adjusted. 153: * 154: * @param keyCount the number of independent DES keys. Can be either 155: * <code>1</code>, <code>2</code> or <code>3</code>. Any other value 156: * will cause an {@link IllegalArgumentException} to be raised. 157: * @param kb the array containing the key bytes to test. MUST have at least 158: * <code>8 * keyCount</code> bytes starting at offset position 159: * <code>offset</code>, otherwise an 160: * {@link ArrayIndexOutOfBoundsException} will be raised. 161: * @param offset the starting offset into the array. 162: * @return <code>true</code> if the bytes in <i>kb</i> starting at 163: * <i>offset</i> are parity adjusted. 164: * @see DES#isParityAdjusted(byte[],int) 165: * @see #adjustParity(int,byte[],int) 166: */ 167: public static boolean isParityAdjusted(int keyCount, byte[] kb, int offset) 168: { 169: if (keyCount < 1 || keyCount > 3) 170: throw new IllegalArgumentException("Invalid keyCount value: " + keyCount); 171: boolean result = DES.isParityAdjusted(kb, offset); 172: if (keyCount > 1) 173: result = result && DES.isParityAdjusted(kb, offset + 8); 174: if (keyCount > 2) 175: result = result && DES.isParityAdjusted(kb, offset + 16); 176: return result; 177: } 178: 179: public Object clone() 180: { 181: return new TripleDES(); 182: } 183: 184: public Iterator blockSizes() 185: { 186: return Collections.singleton(Integer.valueOf(BLOCK_SIZE)).iterator(); 187: } 188: 189: public Iterator keySizes() 190: { 191: ArrayList al = new ArrayList(); 192: al.add(Integer.valueOf(8)); 193: al.add(Integer.valueOf(16)); 194: al.add(Integer.valueOf(24)); 195: return Collections.unmodifiableList(al).iterator(); 196: } 197: 198: public Object makeKey(byte[] kb, int bs) throws InvalidKeyException 199: { 200: if (kb.length != 8 && kb.length != 16 && kb.length != 24) 201: throw new InvalidKeyException("TripleDES key must be 8, 16 or 24 bytes: " 202: + kb.length); 203: Context ctx = new Context(); 204: byte[] k1 = new byte[DES.KEY_SIZE]; 205: System.arraycopy(kb, 0, k1, 0, DES.KEY_SIZE); 206: if (! DES.isParityAdjusted(k1, 0)) 207: DES.adjustParity(k1, 0); 208: ctx.k1 = (DES.Context) des.makeKey(k1, bs); 209: 210: if (kb.length == 8) 211: { 212: ctx.k2 = (DES.Context) des.makeKey(k1, bs); 213: ctx.k3 = (DES.Context) des.makeKey(k1, bs); 214: } 215: else 216: { 217: byte[] k2 = new byte[DES.KEY_SIZE]; 218: System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE); 219: if (! DES.isParityAdjusted(k2, 0)) 220: DES.adjustParity(k2, 0); 221: ctx.k2 = (DES.Context) des.makeKey(k2, bs); 222: 223: byte[] k3 = new byte[DES.KEY_SIZE]; 224: if (kb.length == 16) 225: ctx.k3 = (DES.Context) des.makeKey(k1, bs); 226: else 227: { 228: System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE); 229: if (! DES.isParityAdjusted(k3, 0)) 230: DES.adjustParity(k3, 0); 231: ctx.k3 = (DES.Context) des.makeKey(k3, bs); 232: } 233: } 234: return ctx; 235: } 236: 237: public void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs) 238: { 239: byte[] temp = new byte[BLOCK_SIZE]; 240: des.encrypt(in, i, temp, 0, ((Context) K).k1, bs); 241: des.decrypt(temp, 0, temp, 0, ((Context) K).k2, bs); 242: des.encrypt(temp, 0, out, o, ((Context) K).k3, bs); 243: } 244: 245: public void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs) 246: { 247: byte[] temp = new byte[BLOCK_SIZE]; 248: des.decrypt(in, i, temp, 0, ((Context) K).k3, bs); 249: des.encrypt(temp, 0, temp, 0, ((Context) K).k2, bs); 250: des.decrypt(temp, 0, out, o, ((Context) K).k1, bs); 251: } 252: 253: private final class Context 254: { 255: DES.Context k1, k2, k3; 256: } 257: }