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;
   }

Reply via email to