diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java')
-rw-r--r-- | libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java | 199 |
1 files changed, 130 insertions, 69 deletions
diff --git a/libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java b/libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java index 9b44c9ca7fb..1e98bfc8342 100644 --- a/libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java +++ b/libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java @@ -40,54 +40,50 @@ package gnu.javax.crypto.cipher; import gnu.java.security.Registry; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.security.InvalidKeyException; /** - * Triple-DES, 3DES, or DESede is a <i>combined cipher</i> that uses - * three iterations of the Data Encryption Standard cipher to improve - * the security (at the cost of speed) of plain DES. - * - * <p>Triple-DES runs the DES algorithm three times with three - * independent 56 bit keys. To encrypt:</p> - * - * <blockquote><i>C<sub>i</sub> = - * E<sub>k3</sub> ( E<sub>k2</sub><sup>-1</sup> ( E<sub>k1</sub> ( P<sub>i</sub> )))</i></blockquote> - * - * <p>And to decrypt:</p> - * - * <blockquote><i>P<sub>i</sub> = - * E<sub>k1</sub><sup>-1</sup> ( E<sub>k2</sub> ( E<sub>k3</sub><sup>-1</sup> ( C<sub>i</sub> )))</i></blockquote> - * - * <p>(The "ede" comes from the encryption operation, which runs - * Encrypt-Decrypt-Encrypt)</p> - * - * <p>References:</p> + * Triple-DES, 3DES, or DESede is a <i>combined cipher</i> that uses three + * iterations of the Data Encryption Standard cipher to theoretically improve + * the security of plain DES, at the cost of speed. + * <p> + * Triple-DES runs the DES algorithm three times with one, two or three + * independent 56-bit (DES) keys. When used with one DES key, the cipher behaves + * exactly like a (slower) DES. + * <p> + * To encrypt: + * <blockquote><i>C<sub>i</sub> = E<sub>k3</sub> ( E<sub>k2</sub><sup>-1</sup> ( + * E<sub>k1</sub> ( P<sub>i</sub> )))</i> + * </blockquote> + * <p> + * And to decrypt: + * <blockquote><i>P<sub>i</sub> = E<sub>k1</sub><sup>-1</sup> ( + * E<sub>k2</sub> ( E<sub>k3</sub><sup>-1</sup> ( C<sub>i</sub> )))</i> + * </blockquote> + * <p> + * (The "ede" comes from the encryption operation, which runs + * Encrypt-Decrypt-Encrypt) + * <p> + * References: * <ol> - * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms, - * and Source Code in C, Second Edition</i>. (1996 John Wiley and Sons) - * ISBN 0-471-11709-9. Page 294--295.</li> + * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms, and + * Source Code in C, Second Edition</i>. (1996 John Wiley and Sons) ISBN + * 0-471-11709-9. Page 294--295.</li> * </ol> */ -public class TripleDES extends BaseCipher +public class TripleDES + extends BaseCipher { - - // Constants and variables. - // ----------------------------------------------------------------------- - /** Triple-DES only operates on 64 bit blocks. */ public static final int BLOCK_SIZE = 8; - - /** Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */ + /** By default, Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */ public static final int KEY_SIZE = 24; - /** The underlying DES instance. */ private DES des; - // Constructors. - // ----------------------------------------------------------------------- - /** * Default 0-arguments constructor. */ @@ -97,27 +93,48 @@ public class TripleDES extends BaseCipher des = new DES(); } - // Class methods. - // ----------------------------------------------------------------------- - /** - * Transform a key so it will be parity adjusted. - * - * @param kb The key bytes to adjust. + * Convenience method which calls the method with same name and three + * arguments, passing <code>3</code> as the value of the first parameter. + * + * @param kb The key bytes to adjust. * @param offset The starting offset into the key bytes. - * @see DES#adjustParity(byte[],int) */ public static void adjustParity(byte[] kb, int offset) { + adjustParity(3, kb, offset); + } + + /** + * Adjusts, in-situ, the parity of the designated bytes, so they can be used + * as DES keys for a 3-DES 1-, 2- or 3-key cipher. + * + * @param keyCount the number of independent DES keys. Can be either + * <code>1</code>, <code>2</code> or <code>3</code>. Any other value + * will cause an {@link IllegalArgumentException} to be raised. + * @param kb the array containing the key bytes to adjust. MUST have at least + * <code>8 * keyCount</code> bytes starting at offset position + * <code>offset</code>, otherwise an + * {@link ArrayIndexOutOfBoundsException} will be raised. + * @param offset the starting offset into the array. + * @see DES#adjustParity(byte[],int) + */ + public static void adjustParity(int keyCount, byte[] kb, int offset) + { + if (keyCount < 1 || keyCount > 3) + throw new IllegalArgumentException("Invalid keyCount value: " + keyCount); DES.adjustParity(kb, offset); - DES.adjustParity(kb, offset + 8); - DES.adjustParity(kb, offset + 16); + if (keyCount > 1) + DES.adjustParity(kb, offset + 8); + if (keyCount > 2) + DES.adjustParity(kb, offset + 16); } /** - * Tests if a byte array has already been parity adjusted. - * - * @param kb The key bytes to test. + * Convenience method which calls the method with same name and three + * arguments, passing <code>3</code> as the value of the first parameter. + * + * @param kb The key bytes to test. * @param offset The starting offset into the key bytes. * @return <code>true</code> if the bytes in <i>kb</i> starting at * <i>offset</i> are parity adjusted. @@ -126,13 +143,38 @@ public class TripleDES extends BaseCipher */ public static boolean isParityAdjusted(byte[] kb, int offset) { - return DES.isParityAdjusted(kb, offset) - && DES.isParityAdjusted(kb, offset + 8) - && DES.isParityAdjusted(kb, offset + 16); + return isParityAdjusted(3, kb, offset); } - // Methods implementing BaseCipher. - // ----------------------------------------------------------------------- + /** + * Tests if enough bytes, expected to be used as DES keys for a 3-DES 1-, 2- + * or 3-key cipher, located in a designated byte array, has already been + * parity adjusted. + * + * @param keyCount the number of independent DES keys. Can be either + * <code>1</code>, <code>2</code> or <code>3</code>. Any other value + * will cause an {@link IllegalArgumentException} to be raised. + * @param kb the array containing the key bytes to test. MUST have at least + * <code>8 * keyCount</code> bytes starting at offset position + * <code>offset</code>, otherwise an + * {@link ArrayIndexOutOfBoundsException} will be raised. + * @param offset the starting offset into the array. + * @return <code>true</code> if the bytes in <i>kb</i> starting at + * <i>offset</i> are parity adjusted. + * @see DES#isParityAdjusted(byte[],int) + * @see #adjustParity(int,byte[],int) + */ + public static boolean isParityAdjusted(int keyCount, byte[] kb, int offset) + { + if (keyCount < 1 || keyCount > 3) + throw new IllegalArgumentException("Invalid keyCount value: " + keyCount); + boolean result = DES.isParityAdjusted(kb, offset); + if (keyCount > 1) + result = result && DES.isParityAdjusted(kb, offset + 8); + if (keyCount > 2) + result = result && DES.isParityAdjusted(kb, offset + 16); + return result; + } public Object clone() { @@ -141,32 +183,54 @@ public class TripleDES extends BaseCipher public Iterator blockSizes() { - return Collections.singleton(new Integer(BLOCK_SIZE)).iterator(); + return Collections.singleton(Integer.valueOf(BLOCK_SIZE)).iterator(); } public Iterator keySizes() { - return Collections.singleton(new Integer(KEY_SIZE)).iterator(); + ArrayList al = new ArrayList(); + al.add(Integer.valueOf(8)); + al.add(Integer.valueOf(16)); + al.add(Integer.valueOf(24)); + return Collections.unmodifiableList(al).iterator(); } public Object makeKey(byte[] kb, int bs) throws InvalidKeyException { - if (kb.length != KEY_SIZE) - throw new InvalidKeyException("TripleDES key must be 24 bytes"); - - if (!isParityAdjusted(kb, 0)) - adjustParity(kb, 0); - - byte[] k1 = new byte[DES.KEY_SIZE], k2 = new byte[DES.KEY_SIZE], k3 = new byte[DES.KEY_SIZE]; - System.arraycopy(kb, 0, k1, 0, DES.KEY_SIZE); - System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE); - System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE); + if (kb.length != 8 && kb.length != 16 && kb.length != 24) + throw new InvalidKeyException("TripleDES key must be 8, 16 or 24 bytes: " + + kb.length); Context ctx = new Context(); - + byte[] k1 = new byte[DES.KEY_SIZE]; + System.arraycopy(kb, 0, k1, 0, DES.KEY_SIZE); + if (! DES.isParityAdjusted(k1, 0)) + DES.adjustParity(k1, 0); ctx.k1 = (DES.Context) des.makeKey(k1, bs); - ctx.k2 = (DES.Context) des.makeKey(k2, bs); - ctx.k3 = (DES.Context) des.makeKey(k3, bs); + if (kb.length == 8) + { + ctx.k2 = (DES.Context) des.makeKey(k1, bs); + ctx.k3 = (DES.Context) des.makeKey(k1, bs); + } + else + { + byte[] k2 = new byte[DES.KEY_SIZE]; + System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE); + if (! DES.isParityAdjusted(k2, 0)) + DES.adjustParity(k2, 0); + ctx.k2 = (DES.Context) des.makeKey(k2, bs); + + byte[] k3 = new byte[DES.KEY_SIZE]; + if (kb.length == 16) + ctx.k3 = (DES.Context) des.makeKey(k1, bs); + else + { + System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE); + if (! DES.isParityAdjusted(k3, 0)) + DES.adjustParity(k3, 0); + ctx.k3 = (DES.Context) des.makeKey(k3, bs); + } + } return ctx; } @@ -186,11 +250,8 @@ public class TripleDES extends BaseCipher des.decrypt(temp, 0, out, o, ((Context) K).k1, bs); } - // Inner classes. - // ----------------------------------------------------------------------- - private final class Context { DES.Context k1, k2, k3; } -}
\ No newline at end of file +} |