hello all,
the attached patch adds support for handling 1 and 2, in addition to the
existing 3, DES keys to the triple-DES cipher.
the Mauve test TestOfTripleDES (in gnu.testlet.gnu.javax.crypto.cipher) was
amended to test the new changes.
2006-07-22 Raif S. Naffah <[EMAIL PROTECTED]>
PR Classpath/28100
* gnu/javax/crypto/cipher/TripleDES.java: Updated documentation.
(KEY_SIZE): Likewise.
(adjustParity(int,byte[],int): New method.
(adjustParity(byte[],int): Call above method with 3 as 1st argument.
(isParityAdjusted(int,byte[],int)): New method.
(isParityAdjusted): Call above method with 3 as 1st argument.
(keySizes): Add 8 and 16 as other valid key sizes.
(makeKey): Amended to cater for 1, 2 and 3 independent DES keys.
cheers;
rsn
Index: TripleDES.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/javax/crypto/cipher/TripleDES.java,v
retrieving revision 1.3
diff -u -r1.3 TripleDES.java
--- TripleDES.java 25 Jun 2006 12:01:33 -0000 1.3
+++ TripleDES.java 21 Jul 2006 22:57:54 -0000
@@ -40,17 +40,21 @@
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.
+ * 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 three independent 56 bit
- * keys. To encrypt:
+ * 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>
@@ -75,10 +79,8 @@
{
/** 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;
@@ -92,21 +94,45 @@
}
/**
- * Transform a key so it will be parity adjusted.
+ * 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 [EMAIL PROTECTED] 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
+ * [EMAIL PROTECTED] 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.
+ * 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.
@@ -117,9 +143,37 @@
*/
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);
+ }
+
+ /**
+ * 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 [EMAIL PROTECTED] 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
+ * [EMAIL PROTECTED] 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()
@@ -134,25 +188,49 @@
public Iterator keySizes()
{
- return Collections.singleton(Integer.valueOf(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);
+ 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];
- byte[] k2 = new byte[DES.KEY_SIZE];
- byte[] 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);
- Context ctx = new Context();
+ 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;
}