[e-cvs] cvs commit: e/src/jsrc/org/capml/dom Node.java

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Sat, 25 Aug 2001 15:54:02 -0400


markm       01/08/25 15:54:02

  Modified:    src      Makefile
               src/jsrc/net/vattp/data DES.java Decrypt3DES.java
                        Encrypt3DES.java RecvThread.java SendThread.java
                        StartUpProtocol.java TripleDESKeyConstructor.java
               src/jsrc/net/vattp/security ESecureRandom.java
                        TimerJitterEntropy.java
               src/jsrc/net/vattp/vls VatLocationServer.java
               src/jsrc/org/capml/dom Node.java
  Log:
  integrated Bill's VatTP changes

Revision  Changes    Path
1.109     +2 -2      e/src/Makefile

Index: Makefile
===================================================================
RCS file: /cvs/e/src/Makefile,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -r1.108 -r1.109
--- Makefile	2001/08/24 22:03:06	1.108
+++ Makefile	2001/08/25 19:54:01	1.109
@@ -7,8 +7,8 @@
 
 # Prefix tagging this release's attributes
 PREFIX=tl-E
-DOTVER=0.8.9zd
-TAGVER=0_8_9zd
+DOTVER=0.8.9ze
+TAGVER=0_8_9ze
 RELEASE=working
 
 TOP=..



1.4       +317 -313  e/src/jsrc/net/vattp/data/DES.java

Index: DES.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/vattp/data/DES.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DES.java	2001/07/14 12:57:21	1.3
+++ DES.java	2001/08/25 19:54:01	1.4
@@ -1,7 +1,10 @@
 package net.vattp.data;
-// $Id: DES.java,v 1.3 2001/07/14 12:57:21 markm Exp $
+// $Id: DES.java,v 1.4 2001/08/25 19:54:01 markm Exp $
 //
 // $Log: DES.java,v $
+// Revision 1.4  2001/08/25 19:54:01  markm
+// integrated Bill's VatTP changes
+//
 // Revision 1.3  2001/07/14 12:57:21  markm
 // updoc seems to work
 //
@@ -127,7 +130,7 @@
  * <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>.
  * <br>All rights reserved.
  *
- * <p><b>$Revision: 1.3 $</b>
+ * <p><b>$Revision: 1.4 $</b>
  * @author  Systemics Ltd
  * @author  Geoffrey Keating (this Java implementation)
  * @author  Eric Young
@@ -138,59 +141,59 @@
  */
 public final class DES // must be final for security reasons
 {
-    
-    // Debugging methods and vars.
-    //...........................................................................
-    
-    private static final boolean DEBUG = true;
-    private static final int debuglevel = DEBUG ? 1 : 0;
-    
-    
-    // Native library linking methods and vars.
-    //...........................................................................
-    
-    
-    // DES constants and variables
-    //...........................................................................
-    
-    private static final int
+
+// Debugging methods and vars.
+//...........................................................................
+
+    static private final boolean DEBUG = true;
+    static private final int debuglevel = DEBUG ? 1 : 0;
+
+
+// Native library linking methods and vars.
+//...........................................................................
+
+
+// DES constants and variables
+//...........................................................................
+
+    static private final int
         ROUNDS = 16,                        // number of encryption/decryption rounds
         BLOCK_SIZE = 8,                     // DES block size in bytes
         KEY_LENGTH = 8,                     // DES key length in bytes
         INTERNAL_KEY_LENGTH = ROUNDS * 2;   // number of elements in key schedule
-    
+
     /**
      * State for encrypt/decrypt/uninitialized.
      */
     private int encryptDecryptState = UNINITIALIZED;
-    private static final int UNINITIALIZED = 0;
-    private static final int ENCRYPT = 1;
-    private static final int DECRYPT = 2;
-    
+    static private final int UNINITIALIZED = 0;
+    static private final int ENCRYPT = 1;
+    static private final int DECRYPT = 2;
+
     /**
      * Table for PC2 permutations in key schedule computation.
      */
-    private static final int[] SKB = new int[8 * 64];       // blank final
-    
+    static private final int[] SKB = new int[8 * 64];       // blank final
+
     /**
      * The internal key schedule.
      */
     private int[] sKey = new int[INTERNAL_KEY_LENGTH];
-    
+
     /**
      * Table for S-boxes and permutations, used in encrypt_base.
      */
-    private static final int SP_TRANS[] = new int[8 * 64];  // blank final
-    
-    
-    // Static code
-    //...........................................................................
-    
+    static private final int SP_TRANS[] = new int[8 * 64];  // blank final
+
+
+// Static code
+//...........................................................................
+
     static {
         //
         // build the SKB table
         //
-        
+
         // represent the bit number that each permutated bit is derived from
         // according to FIPS-46
         String cd =
@@ -210,13 +213,13 @@
                 }
             }
         }
-        
+
         //
         // build the SP_TRANS table
         //
-        
+
         // I'd _really_ like to just say 'SP_TRANS = { ... }', but
-        // that would be terribly inefficient (code size + time). 
+        // that would be terribly inefficient (code size + time).
         // Instead we use a compressed representation --GK
         String spt =
             "g3H821:80:H03BA0@N1290BAA88::3112aIH8:8282@0@AH0:1W3A8P810@22;22"+
@@ -228,7 +231,7 @@
             "001@11<8;@82B01P0a2989B:0AY0912889bD0A1@B1A0A0AB033O91182440A9P8"+
             "@I80n@1I03@1J828212A`A8:12B1@19A9@9@8^B:0@H00<82AB030bB840821Q:8"+
             "310A302102::A1::20A1;8"; // OK, try to type _that_!
-        // [526 chars, 3156 bits]
+            // [526 chars, 3156 bits]
         // The theory is that each bit position in each int of SP_TRANS is
         // set in exactly 32 entries. We keep track of set bits.
         offset = 0;
@@ -271,17 +274,17 @@
             }
         }
     }
-    
-    
-    // Constructor, finalizer, and clone()
-    //...........................................................................
-    
+
+
+// Constructor, finalizer, and clone()
+//...........................................................................
+
     /**
      * Constructs a DES cipher object, in the UNINITIALIZED state.
      */
     public DES() {
     }
-    
+
     /**
      * Always throws a CloneNotSupportedException (cloning of ciphers is not
      * supported for security reasons).
@@ -289,18 +292,18 @@
     public final Object clone() throws CloneNotSupportedException {
         throw new CloneNotSupportedException();
     }
-    
-    
-    // Implementation of JCE methods
-    //...........................................................................
-    
+
+
+// Implementation of JCE methods
+//...........................................................................
+
     /**
      * <b>SPI</b>: Returns the length of an input block, in bytes.
      *
      * @return the length in bytes of an input block for this cipher.
      */
     public int blockSize() { return BLOCK_SIZE; }
-    
+
     /**
      * <b>SPI</b>: Initializes this cipher for encryption, using the
      * specified key.
@@ -312,11 +315,11 @@
      *              </ul>
      */
     public void initEncrypt (byte[] key)
-        throws InvalidKeyException {
+    throws InvalidKeyException {
         makeKey(key);
         encryptDecryptState = ENCRYPT;
     }
-    
+
     /**
      * <b>SPI</b>: Initializes this cipher for decryption, using the
      * specified key.
@@ -328,20 +331,20 @@
      *              </ul>
      */
     public void initDecrypt (byte[] key)
-        throws InvalidKeyException {
+    throws InvalidKeyException {
         makeKey(key);
         encryptDecryptState = DECRYPT;
     }
-    
+
     public byte[] crypt(byte[] data) {
         if (data.length != BLOCK_SIZE) {
             throw new IllegalArgumentException("data.length != BLOCK_SIZE");
-        }
-        byte [] ans = new byte[BLOCK_SIZE];
-        update(data, 0, BLOCK_SIZE, ans, 0);
-        return ans;
+	}
+	byte [] ans = new byte[BLOCK_SIZE];
+	update(data, 0, BLOCK_SIZE, ans, 0);
+	return ans;
     }
-    
+
     /**
      * <b>SPI</b>: This is the main method for updating data.
      * <p>
@@ -360,9 +363,9 @@
         if (inLen < 0) throw new IllegalArgumentException("inLen < 0");
         int blockCount = inLen / BLOCK_SIZE;
         inLen = blockCount * BLOCK_SIZE;
-        
+
         boolean doEncrypt = (encryptDecryptState == ENCRYPT);
-        
+
         // Avoid overlapping input and output regions.
         if (in == out && (outOffset >= inOffset && outOffset < (long)inOffset+inLen ||
                           inOffset >= outOffset && inOffset < (long)outOffset+inLen)) {
@@ -371,7 +374,7 @@
             in = newin;
             inOffset = 0;
         }
-        
+
         for (int i = 0; i < blockCount; i++) {
             des(in, inOffset, out, outOffset, doEncrypt);
             inOffset += BLOCK_SIZE;
@@ -379,11 +382,11 @@
         }
         return inLen;
     }
-    
-    
-    // Own methods
-    //...........................................................................
-    
+
+
+// Own methods
+//...........................................................................
+
     /**
      * Expands a user-key to a working key schedule.
      *
@@ -394,31 +397,31 @@
      *              </ul>
      */
     private void makeKey (byte[] userkey)
-        throws InvalidKeyException {
-        
+    throws InvalidKeyException {
+
         if (userkey == null)
             throw new InvalidKeyException(getAlgorithm() + ": Null user key");
-        
+
         if (userkey.length != KEY_LENGTH)
             throw new InvalidKeyException(getAlgorithm() + ": Invalid user key length");
-        
+
         int i = 0;
         int c = (userkey[i++] & 0xFF)       |
-            (userkey[i++] & 0xFF) <<  8 |
-            (userkey[i++] & 0xFF) << 16 |
-            (userkey[i++] & 0xFF) << 24;
+                (userkey[i++] & 0xFF) <<  8 |
+                (userkey[i++] & 0xFF) << 16 |
+                (userkey[i++] & 0xFF) << 24;
         int d = (userkey[i++] & 0xFF)       |
-            (userkey[i++] & 0xFF) <<  8 |
-            (userkey[i++] & 0xFF) << 16 |
-            (userkey[i++] & 0xFF) << 24;
-        
+                (userkey[i++] & 0xFF) <<  8 |
+                (userkey[i++] & 0xFF) << 16 |
+                (userkey[i++] & 0xFF) << 24;
+
         int t = ((d >>> 4) ^ c) & 0x0F0F0F0F;
         c ^= t;
         d ^= t << 4;
         t = ((c << 18) ^ c) & 0xCCCC0000;
-        c ^= t ^ t >>> 18;        
+        c ^= t ^ t >>> 18;
         t = ((d << 18) ^ d) & 0xCCCC0000;
-        d ^= t ^ t >>> 18;        
+        d ^= t ^ t >>> 18;
         t = ((d >>> 1) ^ c) & 0x55555555;
         c ^= t;
         d ^= t << 1;
@@ -428,16 +431,16 @@
         t = ((d >>> 1) ^ c) & 0x55555555;
         c ^= t;
         d ^= t << 1;
-        
+
         d = (d & 0x000000FF) <<  16 |
             (d & 0x0000FF00)        |
             (d & 0x00FF0000) >>> 16 |
             (c & 0xF0000000) >>>  4;
         c &= 0x0FFFFFFF;
-        
+
         int s;
         int j = 0;
-        
+
         for (i = 0; i < ROUNDS; i++) {
             if ((0x7EFC >> i & 1) == 1) {
                 c = (c >>> 2 | c << 26) & 0x0FFFFFFF;
@@ -450,18 +453,18 @@
                 SKB[0x040 | (((c >>>  6) & 0x03) | ((c >>>  7) & 0x3C))] |
                 SKB[0x080 | (((c >>> 13) & 0x0F) | ((c >>> 14) & 0x30))] |
                 SKB[0x0C0 | (((c >>> 20) & 0x01) | ((c >>> 21) & 0x06)
-                             | ((c >>> 22) & 0x38))];
+                                                 | ((c >>> 22) & 0x38))];
             t = SKB[0x100 | ( d         & 0x3F                      )] |
                 SKB[0x140 | (((d >>>  7) & 0x03) | ((d >>>  8) & 0x3c))] |
                 SKB[0x180 | ((d >>> 15) & 0x3F                      )] |
                 SKB[0x1C0 | (((d >>> 21) & 0x0F) | ((d >>> 22) & 0x30))];
-            
+
             sKey[j++] = t <<  16 | (s & 0x0000FFFF);
             s         = s >>> 16 | (t & 0xFFFF0000);
             sKey[j++] = s <<   4 |  s >>> 28;
         }
     }
-    
+
     /**
      * Encrypts/decrypts a block, of length BLOCK_SIZE.
      *
@@ -472,7 +475,7 @@
      * @param  encrypt  true to encrypt, false to decrypt
      */
     private void
-        des (byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
+    des (byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
         int[] lr = {
             (in[inOffset++] & 0xFF)       |
             (in[inOffset++] & 0xFF) <<  8 |
@@ -482,20 +485,20 @@
             (in[inOffset++] & 0xFF) <<  8 |
             (in[inOffset++] & 0xFF) << 16 |
             (in[inOffset  ] & 0xFF) << 24};
-        
+
         initialPermutation(lr);
-        
+
         // do it!
         if (encrypt)
             encrypt_base(lr);
         else
             decrypt_base(lr);
-        
+
         finalPermutation(lr);
-        
+
         int R = lr[0];
         int L = lr[1];
-        
+
         out[outOffset++] = (byte) L;
         out[outOffset++] = (byte)(L >>  8);
         out[outOffset++] = (byte)(L >> 16);
@@ -505,19 +508,19 @@
         out[outOffset++] = (byte)(R >> 16);
         out[outOffset  ] = (byte)(R >> 24);
     }
-    
+
     /** Implements DES encryption without IP and FP. */
     private void encrypt_base (int[] io) {
         int L = io[0];
         int R = io[1];
-        
+
         // look! we fit all four variables (plus the class itself)
         // into short byte-codes!
         int u = R << 1 | R >>> 31;
         R = L << 1 | L >>> 31;
         L = u;
         int t;
-        
+
         for (int i = 0; i < INTERNAL_KEY_LENGTH;) {
             u = R ^ sKey[i++];
             t = R ^ sKey[i++];
@@ -530,7 +533,7 @@
                   SP_TRANS[0x080 | ((u >>>  8) & 0x3F)] |
                   SP_TRANS[0x100 | ((u >>> 16) & 0x3F)] |
                   SP_TRANS[0x180 | ((u >>> 24) & 0x3F)]);
-            
+
             u = L ^ sKey[i++];
             t = L ^ sKey[i++];
             t = t >>> 4 | t << 28;
@@ -546,19 +549,19 @@
         io[0] = R >>> 1 | R << 31;
         io[1] = L >>> 1 | L << 31;
     }
-    
+
     /** Implements DES decryption without IP and FP. */
     private void decrypt_base (int[] io) {
         int L = io[0];
         int R = io[1];
-        
+
         // look! we fit all four variables (plus the class itself)
         // into short byte-codes!
         int u = R << 1 | R >>> 31;
         R = L << 1 | L >>> 31;
         L = u;
         int t;
-        
+
         for (int i = INTERNAL_KEY_LENGTH - 1; i > 0;) {
             t = R ^ sKey[i--];
             u = R ^ sKey[i--];
@@ -571,7 +574,7 @@
                   SP_TRANS[0x080 | ((u >>>  8) & 0x3F)] |
                   SP_TRANS[0x100 | ((u >>> 16) & 0x3F)] |
                   SP_TRANS[0x180 | ((u >>> 24) & 0x3F)]);
-            
+
             t = L ^ sKey[i--];
             u = L ^ sKey[i--];
             t = t >>> 4 | t << 28;
@@ -587,8 +590,8 @@
         io[0] = R >>> 1 | R << 31;
         io[1] = L >>> 1 | L << 31;
     }
-    
-    private static void initialPermutation (int[] io) {
+
+    static private void initialPermutation (int[] io) {
         int L = io[0];
         int R = io[1];
         int t = ((R >>> 4) ^ L) & 0x0F0F0F0F;
@@ -607,8 +610,8 @@
         io[0] = L ^ t;
         io[1] = R ^ (t << 1);
     }
-    
-    private static void finalPermutation (int[] io) {
+
+    static private void finalPermutation (int[] io) {
         int L = io[1];
         int R = io[0];
         int t = (R >>> 1 ^ L) & 0x55555555;
@@ -627,244 +630,244 @@
         io[1] = L ^ t;
         io[0] = R ^ (t << 4);
     }
-    
-    private static String getAlgorithm() { return "DES"; }
-    
-    // Test methods
-    //...........................................................................
-    
+
+  static private String getAlgorithm() { return "DES"; }
+
+// Test methods
+//...........................................................................
+
     /** Entry point for <code>self_test</code>. */
-    public static void main(String[] argv) {
+    static public void main(String[] argv) {
         try {
             self_test();
             // time_test(System.out, "1c587f1c13924fef", "305532286d6f295a", "63fac0d034d9f793");
         } catch (Exception e) { e.printStackTrace(); }
     }
-    
-    private static final String[][] tests =
+
+    static private final String[][] tests =
     {//   KEY                 PLAINTEXT           CIPHERTEXT
         {"0101010101010101", "95f8a5e5dd31d900", "8000000000000000"},
         {"0101010101010101", "dd7f121ca5015619", "4000000000000000"},
         {"0101010101010101", "2e8653104f3834ea", "2000000000000000"},
-        /*
-          {"0101010101010101", "4bd388ff6cd81d4f", "1000000000000000"},
-          {"0101010101010101", "20b9e767b2fb1456", "0800000000000000"},
-          {"0101010101010101", "55579380d77138ef", "0400000000000000"},
-          {"0101010101010101", "6cc5defaaf04512f", "0200000000000000"},
-          {"0101010101010101", "0d9f279ba5d87260", "0100000000000000"},
-          {"0101010101010101", "d9031b0271bd5a0a", "0080000000000000"},
-          {"0101010101010101", "424250b37c3dd951", "0040000000000000"},
-          {"0101010101010101", "b8061b7ecd9a21e5", "0020000000000000"},
-          {"0101010101010101", "f15d0f286b65bd28", "0010000000000000"},
-          {"0101010101010101", "add0cc8d6e5deba1", "0008000000000000"},
-          {"0101010101010101", "e6d5f82752ad63d1", "0004000000000000"},
-          {"0101010101010101", "ecbfe3bd3f591a5e", "0002000000000000"},
-          {"0101010101010101", "f356834379d165cd", "0001000000000000"},
-          {"0101010101010101", "2b9f982f20037fa9", "0000800000000000"},
-          {"0101010101010101", "889de068a16f0be6", "0000400000000000"},
-          {"0101010101010101", "e19e275d846a1298", "0000200000000000"},
-          {"0101010101010101", "329a8ed523d71aec", "0000100000000000"},
-          {"0101010101010101", "e7fce22557d23c97", "0000080000000000"},
-          {"0101010101010101", "12a9f5817ff2d65d", "0000040000000000"},
-          {"0101010101010101", "a484c3ad38dc9c19", "0000020000000000"},
-          {"0101010101010101", "fbe00a8a1ef8ad72", "0000010000000000"},
-          {"0101010101010101", "750d079407521363", "0000008000000000"},
-          {"0101010101010101", "64feed9c724c2faf", "0000004000000000"},
-          {"0101010101010101", "f02b263b328e2b60", "0000002000000000"},
-          {"0101010101010101", "9d64555a9a10b852", "0000001000000000"},
-          {"0101010101010101", "d106ff0bed5255d7", "0000000800000000"},
-          {"0101010101010101", "e1652c6b138c64a5", "0000000400000000"},
-          {"0101010101010101", "e428581186ec8f46", "0000000200000000"},
-          {"0101010101010101", "aeb5f5ede22d1a36", "0000000100000000"},
-          {"0101010101010101", "e943d7568aec0c5c", "0000000080000000"},
-          {"0101010101010101", "df98c8276f54b04b", "0000000040000000"},
-          {"0101010101010101", "b160e4680f6c696f", "0000000020000000"},
-          {"0101010101010101", "fa0752b07d9c4ab8", "0000000010000000"},
-          {"0101010101010101", "ca3a2b036dbc8502", "0000000008000000"},
-          {"0101010101010101", "5e0905517bb59bcf", "0000000004000000"},
-          {"0101010101010101", "814eeb3b91d90726", "0000000002000000"},
-          {"0101010101010101", "4d49db1532919c9f", "0000000001000000"},
-          {"0101010101010101", "25eb5fc3f8cf0621", "0000000000800000"},
-          {"0101010101010101", "ab6a20c0620d1c6f", "0000000000400000"},
-          {"0101010101010101", "79e90dbc98f92cca", "0000000000200000"},
-          {"0101010101010101", "866ecedd8072bb0e", "0000000000100000"},
-          {"0101010101010101", "8b54536f2f3e64a8", "0000000000080000"},
-          {"0101010101010101", "ea51d3975595b86b", "0000000000040000"},
-          {"0101010101010101", "caffc6ac4542de31", "0000000000020000"},
-          {"0101010101010101", "8dd45a2ddf90796c", "0000000000010000"},
-          {"0101010101010101", "1029d55e880ec2d0", "0000000000008000"},
-          {"0101010101010101", "5d86cb23639dbea9", "0000000000004000"},
-          {"0101010101010101", "1d1ca853ae7c0c5f", "0000000000002000"},
-          {"0101010101010101", "ce332329248f3228", "0000000000001000"},
-          {"0101010101010101", "8405d1abe24fb942", "0000000000000800"},
-          {"0101010101010101", "e643d78090ca4207", "0000000000000400"},
-          {"0101010101010101", "48221b9937748a23", "0000000000000200"},
-          {"0101010101010101", "dd7c0bbd61fafd54", "0000000000000100"},
-          {"0101010101010101", "2fbc291a570db5c4", "0000000000000080"},
-          {"0101010101010101", "e07c30d7e4e26e12", "0000000000000040"},
-          {"0101010101010101", "0953e2258e8e90a1", "0000000000000020"},
-          {"0101010101010101", "5b711bc4ceebf2ee", "0000000000000010"},
-          {"0101010101010101", "cc083f1e6d9e85f6", "0000000000000008"},
-          {"0101010101010101", "d2fd8867d50d2dfe", "0000000000000004"},
-          {"0101010101010101", "06e7ea22ce92708f", "0000000000000002"},
-          {"0101010101010101", "166b40b44aba4bd6", "0000000000000001"},
-          {"8001010101010101", "0000000000000000", "95a8d72813daa94d"},
-          {"4001010101010101", "0000000000000000", "0eec1487dd8c26d5"},
-          {"2001010101010101", "0000000000000000", "7ad16ffb79c45926"},
-          {"1001010101010101", "0000000000000000", "d3746294ca6a6cf3"},
-          {"0801010101010101", "0000000000000000", "809f5f873c1fd761"},
-          {"0401010101010101", "0000000000000000", "c02faffec989d1fc"},
-          {"0201010101010101", "0000000000000000", "4615aa1d33e72f10"},
-          {"0180010101010101", "0000000000000000", "2055123350c00858"},
-          {"0140010101010101", "0000000000000000", "df3b99d6577397c8"},
-          {"0120010101010101", "0000000000000000", "31fe17369b5288c9"},
-          {"0110010101010101", "0000000000000000", "dfdd3cc64dae1642"},
-          {"0108010101010101", "0000000000000000", "178c83ce2b399d94"},
-          {"0104010101010101", "0000000000000000", "50f636324a9b7f80"},
-          {"0102010101010101", "0000000000000000", "a8468ee3bc18f06d"},
-          {"0101800101010101", "0000000000000000", "a2dc9e92fd3cde92"},
-          {"0101400101010101", "0000000000000000", "cac09f797d031287"},
-          {"0101200101010101", "0000000000000000", "90ba680b22aeb525"},
-          {"0101100101010101", "0000000000000000", "ce7a24f350e280b6"},
-          {"0101080101010101", "0000000000000000", "882bff0aa01a0b87"},
-          {"0101040101010101", "0000000000000000", "25610288924511c2"},
-          {"0101020101010101", "0000000000000000", "c71516c29c75d170"},
-          {"0101018001010101", "0000000000000000", "5199c29a52c9f059"},
-          {"0101014001010101", "0000000000000000", "c22f0a294a71f29f"},
-          {"0101012001010101", "0000000000000000", "ee371483714c02ea"},
-          {"0101011001010101", "0000000000000000", "a81fbd448f9e522f"},
-          {"0101010801010101", "0000000000000000", "4f644c92e192dfed"},
-          {"0101010401010101", "0000000000000000", "1afa9a66a6df92ae"},
-          {"0101010201010101", "0000000000000000", "b3c1cc715cb879d8"},
-          {"0101010180010101", "0000000000000000", "19d032e64ab0bd8b"},
-          {"0101010140010101", "0000000000000000", "3cfaa7a7dc8720dc"},
-          {"0101010120010101", "0000000000000000", "b7265f7f447ac6f3"},
-          {"0101010110010101", "0000000000000000", "9db73b3c0d163f54"},
-          {"0101010108010101", "0000000000000000", "8181b65babf4a975"},
-          {"0101010104010101", "0000000000000000", "93c9b64042eaa240"},
-          {"0101010102010101", "0000000000000000", "5570530829705592"},
-          {"0101010101800101", "0000000000000000", "8638809e878787a0"},
-          {"0101010101400101", "0000000000000000", "41b9a79af79ac208"},
-          {"0101010101200101", "0000000000000000", "7a9be42f2009a892"},
-          {"0101010101100101", "0000000000000000", "29038d56ba6d2745"},
-          {"0101010101080101", "0000000000000000", "5495c6abf1e5df51"},
-          {"0101010101040101", "0000000000000000", "ae13dbd561488933"},
-          {"0101010101020101", "0000000000000000", "024d1ffa8904e389"},
-          {"0101010101018001", "0000000000000000", "d1399712f99bf02e"},
-          {"0101010101014001", "0000000000000000", "14c1d7c1cffec79e"},
-          {"0101010101012001", "0000000000000000", "1de5279dae3bed6f"},
-          {"0101010101011001", "0000000000000000", "e941a33f85501303"},
-          {"0101010101010801", "0000000000000000", "da99dbbc9a03f379"},
-          {"0101010101010401", "0000000000000000", "b7fc92f91d8e92e9"},
-          {"0101010101010201", "0000000000000000", "ae8e5caa3ca04e85"},
-          {"0101010101010180", "0000000000000000", "9cc62df43b6eed74"},
-          {"0101010101010140", "0000000000000000", "d863dbb5c59a91a0"},
-          {"0101010101010120", "0000000000000000", "a1ab2190545b91d7"},
-          {"0101010101010110", "0000000000000000", "0875041e64c570f7"},
-          {"0101010101010108", "0000000000000000", "5a594528bebef1cc"},
-          {"0101010101010104", "0000000000000000", "fcdb3291de21f0c0"},
-          {"0101010101010102", "0000000000000000", "869efd7f9f265a09"},
-          {"1046913489980131", "0000000000000000", "88d55e54f54c97b4"},
-          {"1007103489988020", "0000000000000000", "0c0cc00c83ea48fd"},
-          {"10071034c8980120", "0000000000000000", "83bc8ef3a6570183"},
-          {"1046103489988020", "0000000000000000", "df725dcad94ea2e9"},
-          {"1086911519190101", "0000000000000000", "e652b53b550be8b0"},
-          {"1086911519580101", "0000000000000000", "af527120c485cbb0"},
-          {"5107b01519580101", "0000000000000000", "0f04ce393db926d5"},
-          {"1007b01519190101", "0000000000000000", "c9f00ffc74079067"},
-          {"3107915498080101", "0000000000000000", "7cfd82a593252b4e"},
-          {"3107919498080101", "0000000000000000", "cb49a2f9e91363e3"},
-          {"10079115b9080140", "0000000000000000", "00b588be70d23f56"},
-          {"3107911598090140", "0000000000000000", "406a9a6ab43399ae"},
-          {"1007d01589980101", "0000000000000000", "6cb773611dca9ada"},
-          {"9107911589980101", "0000000000000000", "67fd21c17dbb5d70"},
-          {"9107d01589190101", "0000000000000000", "9592cb4110430787"},
-          {"1007d01598980120", "0000000000000000", "a6b7ff68a318ddd3"},
-          {"1007940498190101", "0000000000000000", "4d102196c914ca16"},
-          {"0107910491190401", "0000000000000000", "2dfa9f4573594965"},
-          {"0107910491190101", "0000000000000000", "b46604816c0e0774"},
-          {"0107940491190401", "0000000000000000", "6e7e6221a4f34e87"},
-          {"19079210981a0101", "0000000000000000", "aa85e74643233199"},
-          {"1007911998190801", "0000000000000000", "2e5a19db4d1962d6"},
-          {"10079119981a0801", "0000000000000000", "23a866a809d30894"},
-          {"1007921098190101", "0000000000000000", "d812d961f017d320"},
-          {"100791159819010b", "0000000000000000", "055605816e58608f"},
-          {"1004801598190101", "0000000000000000", "abd88e8b1b7716f1"},
-          {"1004801598190102", "0000000000000000", "537ac95be69da1e1"},
-          {"1004801598190108", "0000000000000000", "aed0f6ae3c25cdd8"},
-          {"1002911598100104", "0000000000000000", "b3e35a5ee53e7b8d"},
-          {"1002911598190104", "0000000000000000", "61c79c71921a2ef8"},
-          {"1002911598100201", "0000000000000000", "e2f5728f0995013c"},
-          {"1002911698100101", "0000000000000000", "1aeac39a61f0a464"},
-          {"7ca110454a1a6e57", "01a1d6d039776742", "690f5b0d9a26939b"},
-          {"0131d9619dc1376e", "5cd54ca83def57da", "7a389d10354bd271"},
-          {"07a1133e4a0b2686", "0248d43806f67172", "868ebb51cab4599a"},
-          {"3849674c2602319e", "51454b582ddf440a", "7178876e01f19b2a"},
-          {"04b915ba43feb5b6", "42fd443059577fa2", "af37fb421f8c4095"},
-          {"0113b970fd34f2ce", "059b5e0851cf143a", "86a560f10ec6d85b"},
-          {"0170f175468fb5e6", "0756d8e0774761d2", "0cd3da020021dc09"},
-          {"43297fad38e373fe", "762514b829bf486a", "ea676b2cb7db2b7a"},
-          {"07a7137045da2a16", "3bdd119049372802", "dfd64a815caf1a0f"},
-          {"04689104c2fd3b2f", "26955f6835af609a", "5c513c9c4886c088"},
-          {"37d06bb516cb7546", "164d5e404f275232", "0a2aeeae3ff4ab77"},
-          {"1f08260d1ac2465e", "6b056e18759f5cca", "ef1bf03e5dfa575a"},
-          {"584023641aba6176", "004bd6ef09176062", "88bf0db6d70dee56"},
-          {"025816164629b007", "480d39006ee762f2", "a1f9915541020b56"},
-          {"49793ebc79b3258f", "437540c8698f3cfa", "6fbf1cafcffd0556"},
-          {"4fb05e1515ab73a7", "072d43a077075292", "2f22e49bab7ca1ac"},
-          {"49e95d6d4ca229bf", "02fe55778117f12a", "5a6b612cc26cce4a"},
-          {"018310dc409b26d6", "1d9d5c5018f728c2", "5f4c038ed12b2e41"},
-          {"1c587f1c13924fef", "305532286d6f295a", "63fac0d034d9f793"}
-        */
+/*
+        {"0101010101010101", "4bd388ff6cd81d4f", "1000000000000000"},
+        {"0101010101010101", "20b9e767b2fb1456", "0800000000000000"},
+        {"0101010101010101", "55579380d77138ef", "0400000000000000"},
+        {"0101010101010101", "6cc5defaaf04512f", "0200000000000000"},
+        {"0101010101010101", "0d9f279ba5d87260", "0100000000000000"},
+        {"0101010101010101", "d9031b0271bd5a0a", "0080000000000000"},
+        {"0101010101010101", "424250b37c3dd951", "0040000000000000"},
+        {"0101010101010101", "b8061b7ecd9a21e5", "0020000000000000"},
+        {"0101010101010101", "f15d0f286b65bd28", "0010000000000000"},
+        {"0101010101010101", "add0cc8d6e5deba1", "0008000000000000"},
+        {"0101010101010101", "e6d5f82752ad63d1", "0004000000000000"},
+        {"0101010101010101", "ecbfe3bd3f591a5e", "0002000000000000"},
+        {"0101010101010101", "f356834379d165cd", "0001000000000000"},
+        {"0101010101010101", "2b9f982f20037fa9", "0000800000000000"},
+        {"0101010101010101", "889de068a16f0be6", "0000400000000000"},
+        {"0101010101010101", "e19e275d846a1298", "0000200000000000"},
+        {"0101010101010101", "329a8ed523d71aec", "0000100000000000"},
+        {"0101010101010101", "e7fce22557d23c97", "0000080000000000"},
+        {"0101010101010101", "12a9f5817ff2d65d", "0000040000000000"},
+        {"0101010101010101", "a484c3ad38dc9c19", "0000020000000000"},
+        {"0101010101010101", "fbe00a8a1ef8ad72", "0000010000000000"},
+        {"0101010101010101", "750d079407521363", "0000008000000000"},
+        {"0101010101010101", "64feed9c724c2faf", "0000004000000000"},
+        {"0101010101010101", "f02b263b328e2b60", "0000002000000000"},
+        {"0101010101010101", "9d64555a9a10b852", "0000001000000000"},
+        {"0101010101010101", "d106ff0bed5255d7", "0000000800000000"},
+        {"0101010101010101", "e1652c6b138c64a5", "0000000400000000"},
+        {"0101010101010101", "e428581186ec8f46", "0000000200000000"},
+        {"0101010101010101", "aeb5f5ede22d1a36", "0000000100000000"},
+        {"0101010101010101", "e943d7568aec0c5c", "0000000080000000"},
+        {"0101010101010101", "df98c8276f54b04b", "0000000040000000"},
+        {"0101010101010101", "b160e4680f6c696f", "0000000020000000"},
+        {"0101010101010101", "fa0752b07d9c4ab8", "0000000010000000"},
+        {"0101010101010101", "ca3a2b036dbc8502", "0000000008000000"},
+        {"0101010101010101", "5e0905517bb59bcf", "0000000004000000"},
+        {"0101010101010101", "814eeb3b91d90726", "0000000002000000"},
+        {"0101010101010101", "4d49db1532919c9f", "0000000001000000"},
+        {"0101010101010101", "25eb5fc3f8cf0621", "0000000000800000"},
+        {"0101010101010101", "ab6a20c0620d1c6f", "0000000000400000"},
+        {"0101010101010101", "79e90dbc98f92cca", "0000000000200000"},
+        {"0101010101010101", "866ecedd8072bb0e", "0000000000100000"},
+        {"0101010101010101", "8b54536f2f3e64a8", "0000000000080000"},
+        {"0101010101010101", "ea51d3975595b86b", "0000000000040000"},
+        {"0101010101010101", "caffc6ac4542de31", "0000000000020000"},
+        {"0101010101010101", "8dd45a2ddf90796c", "0000000000010000"},
+        {"0101010101010101", "1029d55e880ec2d0", "0000000000008000"},
+        {"0101010101010101", "5d86cb23639dbea9", "0000000000004000"},
+        {"0101010101010101", "1d1ca853ae7c0c5f", "0000000000002000"},
+        {"0101010101010101", "ce332329248f3228", "0000000000001000"},
+        {"0101010101010101", "8405d1abe24fb942", "0000000000000800"},
+        {"0101010101010101", "e643d78090ca4207", "0000000000000400"},
+        {"0101010101010101", "48221b9937748a23", "0000000000000200"},
+        {"0101010101010101", "dd7c0bbd61fafd54", "0000000000000100"},
+        {"0101010101010101", "2fbc291a570db5c4", "0000000000000080"},
+        {"0101010101010101", "e07c30d7e4e26e12", "0000000000000040"},
+        {"0101010101010101", "0953e2258e8e90a1", "0000000000000020"},
+        {"0101010101010101", "5b711bc4ceebf2ee", "0000000000000010"},
+        {"0101010101010101", "cc083f1e6d9e85f6", "0000000000000008"},
+        {"0101010101010101", "d2fd8867d50d2dfe", "0000000000000004"},
+        {"0101010101010101", "06e7ea22ce92708f", "0000000000000002"},
+        {"0101010101010101", "166b40b44aba4bd6", "0000000000000001"},
+        {"8001010101010101", "0000000000000000", "95a8d72813daa94d"},
+        {"4001010101010101", "0000000000000000", "0eec1487dd8c26d5"},
+        {"2001010101010101", "0000000000000000", "7ad16ffb79c45926"},
+        {"1001010101010101", "0000000000000000", "d3746294ca6a6cf3"},
+        {"0801010101010101", "0000000000000000", "809f5f873c1fd761"},
+        {"0401010101010101", "0000000000000000", "c02faffec989d1fc"},
+        {"0201010101010101", "0000000000000000", "4615aa1d33e72f10"},
+        {"0180010101010101", "0000000000000000", "2055123350c00858"},
+        {"0140010101010101", "0000000000000000", "df3b99d6577397c8"},
+        {"0120010101010101", "0000000000000000", "31fe17369b5288c9"},
+        {"0110010101010101", "0000000000000000", "dfdd3cc64dae1642"},
+        {"0108010101010101", "0000000000000000", "178c83ce2b399d94"},
+        {"0104010101010101", "0000000000000000", "50f636324a9b7f80"},
+        {"0102010101010101", "0000000000000000", "a8468ee3bc18f06d"},
+        {"0101800101010101", "0000000000000000", "a2dc9e92fd3cde92"},
+        {"0101400101010101", "0000000000000000", "cac09f797d031287"},
+        {"0101200101010101", "0000000000000000", "90ba680b22aeb525"},
+        {"0101100101010101", "0000000000000000", "ce7a24f350e280b6"},
+        {"0101080101010101", "0000000000000000", "882bff0aa01a0b87"},
+        {"0101040101010101", "0000000000000000", "25610288924511c2"},
+        {"0101020101010101", "0000000000000000", "c71516c29c75d170"},
+        {"0101018001010101", "0000000000000000", "5199c29a52c9f059"},
+        {"0101014001010101", "0000000000000000", "c22f0a294a71f29f"},
+        {"0101012001010101", "0000000000000000", "ee371483714c02ea"},
+        {"0101011001010101", "0000000000000000", "a81fbd448f9e522f"},
+        {"0101010801010101", "0000000000000000", "4f644c92e192dfed"},
+        {"0101010401010101", "0000000000000000", "1afa9a66a6df92ae"},
+        {"0101010201010101", "0000000000000000", "b3c1cc715cb879d8"},
+        {"0101010180010101", "0000000000000000", "19d032e64ab0bd8b"},
+        {"0101010140010101", "0000000000000000", "3cfaa7a7dc8720dc"},
+        {"0101010120010101", "0000000000000000", "b7265f7f447ac6f3"},
+        {"0101010110010101", "0000000000000000", "9db73b3c0d163f54"},
+        {"0101010108010101", "0000000000000000", "8181b65babf4a975"},
+        {"0101010104010101", "0000000000000000", "93c9b64042eaa240"},
+        {"0101010102010101", "0000000000000000", "5570530829705592"},
+        {"0101010101800101", "0000000000000000", "8638809e878787a0"},
+        {"0101010101400101", "0000000000000000", "41b9a79af79ac208"},
+        {"0101010101200101", "0000000000000000", "7a9be42f2009a892"},
+        {"0101010101100101", "0000000000000000", "29038d56ba6d2745"},
+        {"0101010101080101", "0000000000000000", "5495c6abf1e5df51"},
+        {"0101010101040101", "0000000000000000", "ae13dbd561488933"},
+        {"0101010101020101", "0000000000000000", "024d1ffa8904e389"},
+        {"0101010101018001", "0000000000000000", "d1399712f99bf02e"},
+        {"0101010101014001", "0000000000000000", "14c1d7c1cffec79e"},
+        {"0101010101012001", "0000000000000000", "1de5279dae3bed6f"},
+        {"0101010101011001", "0000000000000000", "e941a33f85501303"},
+        {"0101010101010801", "0000000000000000", "da99dbbc9a03f379"},
+        {"0101010101010401", "0000000000000000", "b7fc92f91d8e92e9"},
+        {"0101010101010201", "0000000000000000", "ae8e5caa3ca04e85"},
+        {"0101010101010180", "0000000000000000", "9cc62df43b6eed74"},
+        {"0101010101010140", "0000000000000000", "d863dbb5c59a91a0"},
+        {"0101010101010120", "0000000000000000", "a1ab2190545b91d7"},
+        {"0101010101010110", "0000000000000000", "0875041e64c570f7"},
+        {"0101010101010108", "0000000000000000", "5a594528bebef1cc"},
+        {"0101010101010104", "0000000000000000", "fcdb3291de21f0c0"},
+        {"0101010101010102", "0000000000000000", "869efd7f9f265a09"},
+        {"1046913489980131", "0000000000000000", "88d55e54f54c97b4"},
+        {"1007103489988020", "0000000000000000", "0c0cc00c83ea48fd"},
+        {"10071034c8980120", "0000000000000000", "83bc8ef3a6570183"},
+        {"1046103489988020", "0000000000000000", "df725dcad94ea2e9"},
+        {"1086911519190101", "0000000000000000", "e652b53b550be8b0"},
+        {"1086911519580101", "0000000000000000", "af527120c485cbb0"},
+        {"5107b01519580101", "0000000000000000", "0f04ce393db926d5"},
+        {"1007b01519190101", "0000000000000000", "c9f00ffc74079067"},
+        {"3107915498080101", "0000000000000000", "7cfd82a593252b4e"},
+        {"3107919498080101", "0000000000000000", "cb49a2f9e91363e3"},
+        {"10079115b9080140", "0000000000000000", "00b588be70d23f56"},
+        {"3107911598090140", "0000000000000000", "406a9a6ab43399ae"},
+        {"1007d01589980101", "0000000000000000", "6cb773611dca9ada"},
+        {"9107911589980101", "0000000000000000", "67fd21c17dbb5d70"},
+        {"9107d01589190101", "0000000000000000", "9592cb4110430787"},
+        {"1007d01598980120", "0000000000000000", "a6b7ff68a318ddd3"},
+        {"1007940498190101", "0000000000000000", "4d102196c914ca16"},
+        {"0107910491190401", "0000000000000000", "2dfa9f4573594965"},
+        {"0107910491190101", "0000000000000000", "b46604816c0e0774"},
+        {"0107940491190401", "0000000000000000", "6e7e6221a4f34e87"},
+        {"19079210981a0101", "0000000000000000", "aa85e74643233199"},
+        {"1007911998190801", "0000000000000000", "2e5a19db4d1962d6"},
+        {"10079119981a0801", "0000000000000000", "23a866a809d30894"},
+        {"1007921098190101", "0000000000000000", "d812d961f017d320"},
+        {"100791159819010b", "0000000000000000", "055605816e58608f"},
+        {"1004801598190101", "0000000000000000", "abd88e8b1b7716f1"},
+        {"1004801598190102", "0000000000000000", "537ac95be69da1e1"},
+        {"1004801598190108", "0000000000000000", "aed0f6ae3c25cdd8"},
+        {"1002911598100104", "0000000000000000", "b3e35a5ee53e7b8d"},
+        {"1002911598190104", "0000000000000000", "61c79c71921a2ef8"},
+        {"1002911598100201", "0000000000000000", "e2f5728f0995013c"},
+        {"1002911698100101", "0000000000000000", "1aeac39a61f0a464"},
+        {"7ca110454a1a6e57", "01a1d6d039776742", "690f5b0d9a26939b"},
+        {"0131d9619dc1376e", "5cd54ca83def57da", "7a389d10354bd271"},
+        {"07a1133e4a0b2686", "0248d43806f67172", "868ebb51cab4599a"},
+        {"3849674c2602319e", "51454b582ddf440a", "7178876e01f19b2a"},
+        {"04b915ba43feb5b6", "42fd443059577fa2", "af37fb421f8c4095"},
+        {"0113b970fd34f2ce", "059b5e0851cf143a", "86a560f10ec6d85b"},
+        {"0170f175468fb5e6", "0756d8e0774761d2", "0cd3da020021dc09"},
+        {"43297fad38e373fe", "762514b829bf486a", "ea676b2cb7db2b7a"},
+        {"07a7137045da2a16", "3bdd119049372802", "dfd64a815caf1a0f"},
+        {"04689104c2fd3b2f", "26955f6835af609a", "5c513c9c4886c088"},
+        {"37d06bb516cb7546", "164d5e404f275232", "0a2aeeae3ff4ab77"},
+        {"1f08260d1ac2465e", "6b056e18759f5cca", "ef1bf03e5dfa575a"},
+        {"584023641aba6176", "004bd6ef09176062", "88bf0db6d70dee56"},
+        {"025816164629b007", "480d39006ee762f2", "a1f9915541020b56"},
+        {"49793ebc79b3258f", "437540c8698f3cfa", "6fbf1cafcffd0556"},
+        {"4fb05e1515ab73a7", "072d43a077075292", "2f22e49bab7ca1ac"},
+        {"49e95d6d4ca229bf", "02fe55778117f12a", "5a6b612cc26cce4a"},
+        {"018310dc409b26d6", "1d9d5c5018f728c2", "5f4c038ed12b2e41"},
+        {"1c587f1c13924fef", "305532286d6f295a", "63fac0d034d9f793"}
+*/
     };
-    
-    private static void self_test()
-        throws Exception {
+
+    static private void self_test()
+    throws Exception {
         DES cryptor = new DES();
         byte[] userKey;
         byte[] tmp, pt, ct;
-        
+
         for (int i = 0; i < tests.length; i++) {
             userKey = hexFromString(tests[i][0]);
             pt = hexFromString(tests[i][1]);
             ct = hexFromString(tests[i][2]);
-            
+
             cryptor.initEncrypt(userKey);
             tmp = cryptor.crypt(pt);
             if (!areEqual(ct, tmp))
-                throw new RuntimeException("encrypt #"+ i +" failed");
-            
+                   throw new RuntimeException("encrypt #"+ i +" failed");
+
             cryptor.initDecrypt(userKey);
             tmp = cryptor.crypt(ct);
-            if (!areEqual(pt, tmp))
+               if (!areEqual(pt, tmp))
                 throw new RuntimeException("decrypt #"+ i +" failed");
         }
-        if (DEBUG && debuglevel > 0) System.out.println("Self-test OK");
+if (DEBUG && debuglevel > 0) System.out.println("Self-test OK");
     }
-    
-    private static boolean areEqual(byte[] a, byte[] b) {
-        if (a.length != b.length) return false;
-        for (int i=0; i<a.length; i++) {
-            if (a[i] != b[i]) return false;
-        }
-        return true;
+
+    static private boolean areEqual(byte[] a, byte[] b) {
+      if (a.length != b.length) return false;
+      for (int i=0; i<a.length; i++) {
+	if (a[i] != b[i]) return false;
+      }
+      return true;
     }
-    
-    private static final String HEXSTR = "0123456789abcdef";
-    private static byte[] hexFromString(String s) {
+
+    static private final String HEXSTR = "0123456789abcdef";
+    static private byte[] hexFromString(String s) {
         s = s.toLowerCase();
         byte[] ans = new byte[s.length()/2];
         for (int i=0; i<s.length(); i++) {
-            if (0 == (i&1)) {
+	    if (0 == (i&1)) {
                 ans[i/2] = (byte)(HEXSTR.indexOf(s.charAt(i)) * 16);
             } else {
                 ans[i/2] += HEXSTR.indexOf(s.charAt(i));
-            }
-        }
-        return ans;
+	    }
+	}
+	return ans;
     }
 /*
-    private static void
+    static private void
     time_test(PrintWriter out, String keyStr, String plainStr, String cipherStr)
     throws InvalidKeyException {
 
@@ -918,13 +921,13 @@
  *
  * Its use is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
  * as long as the following conditions are adhered to.
- * 
+ *
  * Copyright remains Geoffrey Keating's, and as such any Copyright notices in
  * the code are not to be removed.  If this code is used in a product,
  * Geoffrey Keating should be given attribution as the author of the parts used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -937,7 +940,7 @@
  *    must display the following acknowledgement:
  *    This product includes software developed by Geoffrey Keating
  *    (geoffk@discus.anu.edu.au)
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY GEOFFREY KEATING ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -949,20 +952,20 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * 
+ *
  */
 /* Parts of this code (in particular, the string representing SP_TRANS)
  * are Copyright (C) 1995 Eric Young (eay@mincom.oz.au). All rights reserved.
  *
  * Its use is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
  * as long as the following conditions are adhered to.
- * 
+ *
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.  If this code is used in a product,
  * Eric Young should be given attribution as the author of the parts used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -974,7 +977,7 @@
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    This product includes software developed by Eric Young (eay@mincom.oz.au)
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -987,3 +990,4 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+



1.3       +7 -6      e/src/jsrc/net/vattp/data/Decrypt3DES.java

Index: Decrypt3DES.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/vattp/data/Decrypt3DES.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Decrypt3DES.java	2001/07/14 12:57:21	1.2
+++ Decrypt3DES.java	2001/08/25 19:54:01	1.3
@@ -71,7 +71,7 @@
         return val;
     }
 
-    /*package*/ void init() {   
+    /*package*/ void init() {
         if (null != myCurrentBlock) {
             increment(myIV);
         } else {
@@ -81,9 +81,9 @@
     }
 
     /*package*/ void transform(byte[] buffer, int off, int len) {
-        
+
         long startTime = Trace.comm.timing ? MicroTime.queryTimer() : 0;
-        Assertion.test(0==(len&0x7), 
+        Assertion.test(0==(len&0x7),
                        "Buffer length not a multiple of 8, len = "
                        + len);
 
@@ -98,7 +98,7 @@
             System.arraycopy(myCurrentBlock,0, myPreviousBlock,0, 8);
         }
         if (Trace.comm.timing && Trace.ON) {
-            Trace.comm.timingm("Pkt3DESDecrypt(" + buffer.length + "), time " 
+            Trace.comm.timingm("Pkt3DESDecrypt(" + buffer.length + "), time "
                 + (MicroTime.queryTimer() - startTime) + " microseconds");
         }
     }
@@ -107,14 +107,14 @@
         for (int i=0; i<8; i++) inOut[off+i] ^= in[i];
     }
 
-    private void increment(byte[] value) { 
+    private void increment(byte[] value) {
         for (int i=value.length-1; i>=0; i--) {
             byte v = (value[i] += 1);
             if (0 != v) break;
         }
     }
 
-    private static String eightToHex(byte[] b, int offset) {
+    static private String eightToHex(byte[] b, int offset) {
         String ret = "";
         for (int i=offset; i<offset+8; i++) {
             ret += "0123456789abcdef".charAt((b[i]>>4)&0xf);
@@ -123,3 +123,4 @@
         return ret;
     }
 }
+



1.3       +15 -11    e/src/jsrc/net/vattp/data/Encrypt3DES.java

Index: Encrypt3DES.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/vattp/data/Encrypt3DES.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Encrypt3DES.java	2001/07/14 12:57:21	1.2
+++ Encrypt3DES.java	2001/08/25 19:54:01	1.3
@@ -33,15 +33,17 @@
 
     private byte[] myIV;
     private byte[] myDESKeys;
+    private boolean myIsStandardCBC;
 
     private final byte[] myPreviousBlock = new byte[8];
 
     private final byte[] myPad = new byte[8];
     private DES myDes1, myDes2, myDes3;
 
-    /*package*/ Encrypt3DES(byte[] desKeys, byte[] iv) {
+    /*package*/ Encrypt3DES(byte[] desKeys, byte[] iv, boolean isStandardCBC) {
         myDESKeys = desKeys;
         myIV = iv;
+        myIsStandardCBC = isStandardCBC;
         try {
             byte[] key = new byte[8];
             System.arraycopy(myDESKeys, 0, key, 0, 8);
@@ -58,18 +60,17 @@
             Trace.comm.errorm("Problem initializing DES keys", e);
             throw new NestedException("Problem initializing DES keys", e);
         }
-        init();
-    }
-
-    /*package*/ void init() {    //Only needed if flush not used
         System.arraycopy(myIV,0, myPreviousBlock,0, 8);
     }
 
+    /*package*/ void init() {}  // NOP
+
     /*package*/ byte[] getSuspendInfo() {
         if (Trace.comm.debug & Trace.ON) {
             Trace.comm.debugm("Returning IV=" + eightToHex(myIV,0));
         }
-        return myIV;
+        if (myIsStandardCBC) return myPreviousBlock;
+        else return myIV;
     }
 
     /*package*/ void transform(byte[] buffer, int off, int len) {
@@ -77,7 +78,10 @@
         if (0 != (len&7)) {
             Assertion.test(false, "Length must be a multiple of 8, len="+len);
         }
-        System.arraycopy(myIV,0, myPreviousBlock,0, 8);
+        if (!myIsStandardCBC) {
+            System.arraycopy(myIV,0, myPreviousBlock,0, 8);
+            increment(myIV);
+        }
         for (int cursor=off; cursor<off+len; cursor+=8) {
             if (Trace.comm.verbose && Trace.ON) {
                 Trace.comm.verbosem("Plaintext=" + eightToHex(buffer, cursor));
@@ -89,9 +93,8 @@
             myDes3.update(buffer, cursor, 8, buffer, cursor);
             System.arraycopy(buffer, cursor, myPreviousBlock,0, 8);
         }
-        increment(myIV);
         if (Trace.comm.timing && Trace.ON) {
-            Trace.comm.timingm("Pkt3DESEncrypt(" + buffer.length + "), time " 
+            Trace.comm.timingm("Pkt3DESEncrypt(" + buffer.length + "), time "
                 + (MicroTime.queryTimer() - startTime) + " microseconds");
         }
     }
@@ -101,14 +104,14 @@
         for (int i=0; i<8; i++) inOut[offset+i] ^= in[i];
     }
 
-    private void increment(byte[] value) { 
+    private void increment(byte[] value) {
         for (int i=value.length-1; i>=0; i--) {
             byte v = (value[i] += 1);
             if (0 != v) break;
         }
     }
 
-    private static String eightToHex(byte[] b, int offset) {
+    static private String eightToHex(byte[] b, int offset) {
         String ret = "";
         for (int i=offset; i<offset+8; i++) {
             ret += "0123456789abcdef".charAt((b[i]>>4)&0xf);
@@ -117,3 +120,4 @@
         return ret;
     }
 }
+



1.4       +203 -70   e/src/jsrc/net/vattp/data/RecvThread.java

Index: RecvThread.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/vattp/data/RecvThread.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- RecvThread.java	2001/07/14 12:57:21	1.3
+++ RecvThread.java	2001/08/25 19:54:01	1.4
@@ -50,11 +50,17 @@
  */
 /*package*/ class RecvThread extends Thread {
     // Index: 2=transforming, 1=isDoingMac
-    //                                             0   1   2   3 
-    static private final int[] theHeaderLengths = {4, 24, -1, 24};
+    static private final int HEADER_INVALID    = -1;
+    static private final int HEADER_INT_LENGTH = 0;
+    static private final int HEADER_VLEN_SHA1  = 1;
+    static private final int HEADER_VLEN_HMAC  = 2;
+    // Note that the header lengths must be a multiple of the blocksize
+    // of the encryption used (8 for 3DES).  AES implementation take warning.
+    //                                             0   1   2
+    static private final int[] theHeaderLengths = {4, 24, 32};
     
     /** Notify DataPath every NOTIFY_EVERY bytes of receive progress */
-    private static final int NOTIFY_EVERY = 10000;
+    static private final int NOTIFY_EVERY = 10000;
     
     private InputStream myInputStream;
     private DataPath myDataPath;
@@ -75,9 +81,13 @@
     // support for future HTTP tunnelling.   It could also be used to 
     // implement a dynamic table dependent compressiong scheme.
     private MsgTransformer myTransform = null;
+    private boolean myIsStandardCBC = false;
 
     // The following fields are for MAC calculation
+    // HASH_BLOCK_SIZE is true for MD5 and SHA1, check others
+    static private final int HASH_BLOCK_SIZE = 64;
     private boolean myIsDoingMac = false;
+    private boolean myIsDoingHMAC = false;
     private byte[] myMACKey;
     private MessageDigest mySHA1;
     private byte[] myMAC;
@@ -124,6 +134,8 @@
             if (t instanceof VirtualMachineError) throw (VirtualMachineError)t;
             if (t instanceof ThreadDeath) throw (ThreadDeath)t;
             if (t instanceof LinkageError) throw (LinkageError)t;
+            //XXX if it's not one of these, shouldn't we at least trace it, 
+            //and perhaps rethrow it?
         }
     }
     /**
@@ -140,54 +152,69 @@
      * suite.
      */
 
-    /*package*/ void changeProtocol(
-                AuthSecrets protocolParms) {
+    /*package*/ void changeProtocol(AuthSecrets protocolParms) {
         if (Trace.comm.verbose && Trace.ON) {
             Trace.comm.verbosem("ProtocolChange, pp="+protocolParms);
         }
-        Assertion.test(myChangeProtocolIsOk, 
-                "Must only be called while caller is processing an input message");
-        int headerLengthIndex = 0;          // For calculating the header length
+        Assertion.test(myChangeProtocolIsOk,
+            "Must only be called while caller is processing an input message");
+        // For calculating the header length
+        int headerLengthIndex = HEADER_INVALID; 
 
         if (StartUpProtocol.PROTO_NONE.equals(protocolParms.myProtocolSuite)) {
             myIsAggragating = false;
             myIsDoingMac = false;
+            mySequence = null;
+            headerLengthIndex = HEADER_INT_LENGTH;
         // begin daffE -> E
         } else if (StartUpProtocol.PROTO_3DES_SDH_M.equals(
-                        protocolParms.myProtocolSuite)) {
+                   protocolParms.myProtocolSuite)) {
             myIsAggragating = true;
             MessageDigest md5 = setSHA1(protocolParms);
-            headerLengthIndex = 3;
+            headerLengthIndex = HEADER_VLEN_SHA1;
             mySequence = null;
-            byte[] raw_3des_key = TripleDESKeyConstructor.make(protocolParms.myDHSecret);
-            // myTransform = new TripleDESMsgEncryptor(protocolParms.myIncomingSequence, raw_3des_key, false);
-            myTransform = new Decrypt3DES(raw_3des_key, protocolParms.myIncomingSequence);
+            byte[] raw_3des_key = 
+              TripleDESKeyConstructor.make(protocolParms.myDHSecret);
+            myTransform = 
+              new Decrypt3DES(raw_3des_key, protocolParms.myIncomingSequence);
         // end daffE -> E
-        } else if (StartUpProtocol.PROTO_AUTH_SDH_M.equals(
-                        protocolParms.myProtocolSuite)) {
-            myIsAggragating = true;
-            MessageDigest md5 = setSHA1(protocolParms);
-            headerLengthIndex = 3;
-            mySequence = protocolParms.myIncomingSequence;
-            myTransform = null;
-        } else if (StartUpProtocol.PROTO_NONE_SDH_M.equals(
-                        protocolParms.myProtocolSuite)) {
+        // begin improved E protocol
+        } else if (StartUpProtocol.PROTO_3DES_SDH_M2.equals(
+                   protocolParms.myProtocolSuite)) {
             myIsAggragating = true;
             MessageDigest md5 = setSHA1(protocolParms);
-            headerLengthIndex = 3;
-            myTransform = null;
+            headerLengthIndex = HEADER_VLEN_HMAC;
+            mySequence = new byte[4];  // Assume initialized to zero
+            byte[] raw_3des_key = 
+              TripleDESKeyConstructor.make(protocolParms.myDHSecret);
+            myTransform = 
+              new Decrypt3DES(raw_3des_key, protocolParms.myIncomingSequence);
+            myTransform.init();
+            myIsStandardCBC = true;
+            myIsDoingHMAC = true;
+        // end improved E protocol
         } else {
             Assertion.test(false, "Invalid protocol type "+protocolParms);
         }
         myIsCompressingMsgLengths = myIsAggragating;
 
         int len = theHeaderLengths[headerLengthIndex];
-        Assertion.test(len >= 0, "Invalid combination of link options");
+        Assertion.test(len >= 0, "Invalid header length code");
         myHeader = new byte[len];
     }
+
     private byte[] computeMAC(Vector messages) throws IOException {
         mySHA1.reset();                 //Initialize a new hash
-        mySHA1.update(myMACKey);            // The MAC key
+        if (myIsDoingHMAC) {
+            /* Calculate sha1(key ^ ipad || data) */
+            byte[] pad = new byte[HASH_BLOCK_SIZE];
+            replicate(pad, (byte)0x36);
+            xor(pad, myMACKey);
+            mySHA1.reset();
+            mySHA1.update(pad);
+        } else {
+            mySHA1.update(myMACKey);            // The MAC key
+        }
         if (null != mySequence) {
             mySHA1.update(mySequence);
             increment(mySequence);
@@ -197,12 +224,26 @@
             byte[] b = (byte[])(itr.nextElement());
             int len = b.length;
             byte[] l = new byte[4];
-            int lenlen = SendThread.msgLength(len, l, 0, myIsCompressingMsgLengths);
+            int lenlen = SendThread.msgLength(len, l, 0,
+                                              myIsCompressingMsgLengths);
             mySHA1.update(l, 0, lenlen);
             mySHA1.update(b);                   // The message
         }
-        return mySHA1.digest(myMACKey);     // The MAC key again
+        if (myIsDoingHMAC) {
+            byte[] hash = mySHA1.digest();
+
+            /* Calculate sha1(key ^ opad || hash */
+            byte[] pad = new byte[HASH_BLOCK_SIZE];
+            replicate(pad, (byte)0x5c);
+            xor(pad, myMACKey);
+            mySHA1.update(pad);
+            mySHA1.update(hash);
+            return mySHA1.digest();
+        } else {
+            return mySHA1.digest(myMACKey);     // The MAC key again
+        }
     }
+    
     private void fillArray(byte[] b, int off, int len) throws IOException {
         int offset = off;
         while (offset < off + len) {
@@ -216,6 +257,7 @@
             callDataPath(new DataCommThunk(myDataPath)); //progress notify
         }
     }
+    
     /**
      * Get the current message sequence number
      */
@@ -226,26 +268,74 @@
             return mySequence;
         }
     }
+    
     private void increment(byte[] value) { 
         for (int i=value.length-1; i>=0; i--) {
             byte v = (value[i] += 1);
             if (0 != v) break;
         }
+    }
+    
+    
+    /**
+     * isEqual - Compare two byte arrays.
+     *
+     * @param a is the first input array.
+     * @param b is the second input array.
+     * @return is true if the two arrays contain all the same bytes,
+     *         else false. 
+     */
+    static private boolean isEqual(byte[] a, byte[] b) {
+        int len = a.length;
+        if (len != b.length) return false;
+        for (int i=0; i<len; i++) {
+            if (a[i] != b[i]) return false;
+        }
+        return true;
+    }
+    
+    
+    /**
+     * xor - Exclusive OR two byte arrays.
+     *
+     * @param a is the input and output array.
+     * @param b is the array which is XORed with a.
+     */
+    static private void xor(byte[] a, byte[] b) {
+        int len = Math.min(a.length, b.length);
+        for (int i=0; i<len; i++) {
+            a[i] ^= b[i];
+        }
+    }
+    
+    
+    /**
+     * replicate - Copy a single byte to all elements of a byte array.
+     *
+     * @param a is the byte array.
+     * @param v is the byte to be replicated.
+     */
+    static private void replicate(byte[] a, byte v) {
+        for (int i=0; i<a.length; i++) {
+            a[i] = v;
+        }
     }
-  /**
-   * Calculate the MD5 hash of some data with a specific padding.
-   * <p>
-   * The padding allows different values to be obtained from the same data
-   * by varing the padding value.  We use it to get the different 
-   * authentication values from the same Diffie Hellman shared secret.
-   *
-   * @param pad The int (treated as a byte) to be used to pad the MD5 calculation.
-   * @param data The data to be hashed.
-   * @param md5 The message digest object to be used.
-   *
-   * @return A byte array representing the hash.
-   */
 
+    
+    /**
+     * Calculate the MD5 hash of some data with a specific padding.
+     * <p>
+     * The padding allows different values to be obtained from the same data
+     * by varing the padding value.  We use it to get the different 
+     * authentication values from the same Diffie Hellman shared secret.
+     *
+     * @param pad The int (treated as a byte) to be used to pad the MD5 
+     *            calculation. 
+     * @param data The data to be hashed.
+     * @param md5 The message digest object to be used.
+     *
+     * @return A byte array representing the hash.
+     */
     private byte[] md5Hash(int pad, byte[] data, MessageDigest md5) {
         byte[] mdConst = new byte[16];
         for (int i=0; i<mdConst.length; i++) mdConst[i] = (byte)pad;
@@ -265,8 +355,12 @@
         fillArray(myHeader, 0, myHeader.length);
 
         if (null != myTransform) {
-            if (Trace.comm.timing && Trace.ON) startTime = MicroTime.queryTimer();
-            myTransform.init();
+            if (Trace.comm.timing && Trace.ON) {
+                startTime = MicroTime.queryTimer();
+            }
+            if (!myIsStandardCBC) {
+                myTransform.init();
+            }
             myTransform.transform(myHeader);
             if (Trace.comm.timing && Trace.ON) {
                 authTime += MicroTime.queryTimer() - startTime;
@@ -278,32 +372,32 @@
         }
 
         int length;
-        int blockOffset = 0; // Message data read with header
+        int nextItemOffset;    // Offset to the next item in the header
         if (myIsCompressingMsgLengths) {
             int l1 = myHeader[0];    // First byte of the length
             if (0 == (l1 & 0x80)) {           // len < 128
                 length = l1;
-                blockOffset = 3;
+                nextItemOffset = 1;
             } else {
                 if (0x80 == (l1 & 0xc0)) { // len < 16,384
                     length = ((l1 & 0x3f) << 8) |
                              ((myHeader[1] & 0xff));
-                    blockOffset = 2;
+                    nextItemOffset = 2;
                 } else if (0xc0 == (l1 & 0xe0)) { // len < 2,097,152
                     length = ((l1 & 0x1f)          << 16) |
                              ((myHeader[1] & 0xff) <<  8) |
                              ((myHeader[2] & 0xff))       ;
-                    blockOffset = 1;
+                    nextItemOffset = 3;
                 } else if (0xe0 == (l1 & 0xf0)) { // len < 2**28
                     length = ((l1 & 0x0f)          << 24) |
                              ((myHeader[1] & 0xff) << 16) |
                              ((myHeader[2] & 0xff) <<  8) |
                              ((myHeader[3] & 0xff))       ;
-                    // blockOffset = 0; already set
+                    nextItemOffset = 4;
                 } else {
-                    throw new IOException(
-                            "Invalid compressed length code"
-                            + HexStringUtils.byteArrayToReadableHexString(myHeader));
+                    throw new IOException
+                      ("Invalid compressed length code" +
+                       HexStringUtils.byteArrayToReadableHexString(myHeader));
                 }
             }
         } else {            // Not compressing
@@ -311,6 +405,7 @@
                      ((myHeader[1] & 0xff) << 16) |
                      ((myHeader[2] & 0xff) <<  8) |
                       (myHeader[3] & 0xff)        ;
+            nextItemOffset = 4;
         }
         if (Trace.comm.verbose && Trace.ON) {
             Trace.comm.verbosem("incoming packet len = " + length);
@@ -318,37 +413,75 @@
         if (length > Msg.MAX_INBOUND_MSG_LENGTH || length < 0) {
             throw new IOException("Packet too large: " + length +
                                   " > " + Msg.MAX_INBOUND_MSG_LENGTH);
+        }
+        if (myIsDoingMac) {
+            System.arraycopy(myHeader, nextItemOffset,
+                         myMAC, 0, 20); // Save MAC
+            nextItemOffset += 20;
+        }
+        if (null != mySequence) {
+            int seqLen = mySequence.length;
+            byte[] theirSequence = new byte[seqLen];
+            System.arraycopy(myHeader, nextItemOffset, 
+                             theirSequence, 0, 
+                             seqLen);
+            if (!isEqual(mySequence, theirSequence)) {
+                if (Trace.comm.error) {
+                    traceErrorMessage(theirSequence,
+                            0, theirSequence.length,
+                            "sequence error, [remote sequence number]:");
+                    traceErrorMessage(mySequence,
+                            0, mySequence.length,
+                            "sequence error, [local sequence number]:");
+                }
+                throw new IOException("incoming packet sequence error");
+            }
+            nextItemOffset += seqLen;
+        }
+        // Calculate message length + padding and allocate a buffer
+        // The length required is the length of the data portion plus the
+        // padding length for the original message.
+        // The padding length for the original message is calculated:
+        //    msglen = (length_of_length + length_of_headers + length_of_data
+        //    padlen = ((msglen + 7) & 0xfffffff8) - msglen
+        // length_of_length + length_of_headers is equal to nextItemOffset
+        //    (the amount of data eaten by processing them above).
+        // length_of_data is length.
+        byte[] message;
+        if (myIsCompressingMsgLengths || null != myTransform) {
+            int msglen = nextItemOffset + length;
+            int padlen = ((msglen + 7) & 0xfffffff8) - msglen;
+            message = new byte[length + padlen];
+        } else {
+            message = new byte[length];
         }
-        byte[] message = new byte[
-                        (myIsCompressingMsgLengths || null != myTransform) 
-                                ? ((length-blockOffset+7)
-                                        &0xfffffff8)
-                                        + blockOffset
-                                : length];
-        if (blockOffset > 0) {
+        if (nextItemOffset < myHeader.length) {
             // Copy compressed data read with header
-            System.arraycopy(myHeader,24-blockOffset,
-                             message,0, 
-                             blockOffset);
+            System.arraycopy(myHeader, nextItemOffset,
+                             message, 0,
+                             myHeader.length - nextItemOffset);
         }
         if (Trace.comm.verbose && Trace.ON) {
             Trace.comm.verbosem("Initial message: "
                 + HexStringUtils.byteArrayToReadableHexString(message));
         }
-        if (myIsDoingMac) {
-            System.arraycopy(myHeader,4-blockOffset,
-                         myMAC, 0, 20); // Save MAC
-        }
 
         // Read rest of message into the buffer allocated for it
-        fillArray(message, blockOffset, message.length-blockOffset);
+        fillArray(message,
+                  myHeader.length - nextItemOffset,
+                  message.length - (myHeader.length - nextItemOffset));
 
         if (null != myTransform) {
-            if (Trace.comm.timing && Trace.ON) startTime = MicroTime.queryTimer();
-            myTransform.transform(message, blockOffset,
-                            message.length - blockOffset);
-            if (Trace.comm.timing && Trace.ON) authTime += MicroTime.queryTimer() - startTime;
+            if (Trace.comm.timing && Trace.ON) {
+                startTime = MicroTime.queryTimer();
+            }
+            myTransform.transform(message, (myHeader.length-nextItemOffset),
+                            message.length - (myHeader.length-nextItemOffset));
+            if (Trace.comm.timing && Trace.ON) {
+                authTime += MicroTime.queryTimer() - startTime;
+            }
         }
+        
         if (Trace.comm.verbose && Trace.ON) {
             Trace.comm.verbosem("Full message: "
                 + HexStringUtils.byteArrayToReadableHexString(message));



1.4       +180 -95   e/src/jsrc/net/vattp/data/SendThread.java

Index: SendThread.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/vattp/data/SendThread.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SendThread.java	2001/08/20 05:07:43	1.3
+++ SendThread.java	2001/08/25 19:54:01	1.4
@@ -44,46 +44,47 @@
 import java.util.Vector;
 
 /**
-   A thread for writing data to an OutputStream that might block.
-   Incoming chunks of data are enqueued.  The thread dequeues chunks
-   and writes them.  Exceptions during the actual writing are sent to
-   the RawConnection for delivery back into the vat via
-   noticeProblem().
-<p>
- This class generates network packets in the following forms:
-
- <p>If no authentication, no mac, no aggragation: (dataLength, data)
-
- <p>If authentication, mac, aggragation:
-            (n,commlength) (mac) (msg1len, msg1, msg2len, msg2 ...) (pad)
-
-    <p> commLength is the length of the data in the message on the comm link.
-
-    <p>If commLength < 128 (2**7) then n == 1.  (One high bit zero)
-       If commLength < 16,384 (2**14) then n == 2.  (Two high bits are 10)
-       If commLength < 2,097,152 (2**21) then n == 3.  (Three high bits are 110).
-          <p>Since the maximum length packet is currently 1024*1024, the above
-          encoding is sufficent.  If longer packets become supported, then
-          If commLength < 2**28 then n == 4.  (Four high bits are 1110) and
-          If commLength < 2**31 then n == 5.  (Five high bits are 11110).
-          N.B. In Java, array.length is a 31 bit int, limiting the maximum
-          length we must support.
-
-    <p>The MAC is always calculated over the aggragated data.  N.B. the
-    message building logic prepends a 4 byte message length field to each 
-    message, so the MAC includes the message length(s).
-
-    <p> pad is padding to make the actual packet length a multiple of the
-    basic block size.
-
-    <p>The whole packet is authenticated with the authentication algorthm and mode
-    specified when authentication is turned on.
-   @author Bill Frantz
+ * A thread for writing data to an OutputStream that might block.
+ * Incoming chunks of data are enqueued.  The thread dequeues chunks
+ * and writes them.  Exceptions during the actual writing are sent to
+ * the RawConnection for delivery back into the vat via
+ * noticeProblem().
+ * <p>
+ * This class generates network packets in the following forms:
+ * <p>
+ * If no authentication, no mac, no aggragation: (dataLength, data)
+ * <p>
+ * If authentication, mac, aggragation:
+ *          (n,commlength) (mac) (msg1len, msg1, msg2len, msg2 ...) (pad)
+ * <p>
+ * commLength is the length of the data in the message on the comm link.
+ * <p>
+ * If commLength < 128 (2**7) then n == 1.  (One high bit zero)
+ * If commLength < 16,384 (2**14) then n == 2.  (Two high bits are 10)
+ * If commLength < 2,097,152 (2**21) then n == 3.  (Three high bits are 110).
+ * <p>
+ *        Since the maximum length packet is currently 1024*1024, the above
+ *        encoding is sufficent.  If longer packets become supported, then
+ *        If commLength < 2**28 then n == 4.  (Four high bits are 1110) and
+ *        If commLength < 2**31 then n == 5.  (Five high bits are 11110).
+ *        N.B. In Java, array.length is a 31 bit int, limiting the maximum
+ *        length we must support.
+ * <p>
+ *  The MAC is always calculated over the aggragated data.  N.B. the
+ *  message building logic prepends a 4 byte message length field to each 
+ *  message, so the MAC includes the message length(s).
+ * <p>
+ *  pad is padding to make the actual packet length a multiple of the
+ *  basic block size.
+ * <p>
+ *  The whole packet is authenticated with the authentication algorthm and 
+ *  mode specified when authentication is turned on.
+ * @author Bill Frantz
  */
 /*package*/ class SendThread extends Thread {
     
     /** Notify DataPath every NOTIFY_EVERY bytes of send progress */
-    private static final int NOTIFY_EVERY = 10000;
+    static private final int NOTIFY_EVERY = 10000;
 
     private OutputStream myOutputStream;
     private Socket mySocket;
@@ -100,7 +101,7 @@
     private Hashtable myAddressesTried;
 
     // The following fields are for aggragating messages
-    private static final int MAX_AGGRAGATION = 1024;
+    static private final int MAX_AGGRAGATION = 1024;
     private boolean myIsAggragating = false;
     private int myAggragateLength;
     private byte[] myAggragation = new byte[MAX_AGGRAGATION];
@@ -111,10 +112,14 @@
     // support for future HTTP tunnelling.   It could also be used to 
     // implement a dynamic table dependent compressiong scheme.
     private MsgTransformer myTransform = null;
+    private boolean myIsStandardCBC = false;
 
     // The following fields are for MAC calculation
+    // HASH_BLOCK_SIZE is true for MD5 and SHA1, check others
+    static private final int HASH_BLOCK_SIZE = 64;
     private boolean myIsDoingMac = false;
-    private byte[] myMacKey;
+    private boolean myIsDoingHMAC = false;
+    private byte[] myMACKey;
     private MessageDigest mySHA1;
     private int myMacLen = 0;
     private byte[] mySequence;  // Sequence check
@@ -175,6 +180,12 @@
         if (null == myRunner) throw new NullPointerException("Bad Runner");
         this.start();
     }
+
+    /**
+     * Add an element to the aggrated message being constructed.
+     *
+     * @param elem is the element to be added.
+     */
     private void addElement(Object elem) throws IOException {
         if (elem instanceof byte[]) {
             byte[] b = (byte[]) elem;
@@ -182,7 +193,7 @@
                 Trace.comm.verbosem("to=" + myRemoteAddr
                             + " addElement="+b.length);
             }
-            if (!myIsAggragating 
+            if (!myIsAggragating
                     || myAggragateLength + b.length+4 > myAggragation.length) {
                 flushElements();
                 if (b.length+4 > myAggragation.length) {
@@ -191,10 +202,8 @@
                 }
             }
             int len = b.length;
-            myAggragateLength = msgLength(len,
-                                          myAggragation,
-                                          myAggragateLength,
-                                          myIsCompressingMsgLengths);
+            myAggragateLength = msgLength(len, myAggragation,
+                                    myAggragateLength, myIsCompressingMsgLengths);
             System.arraycopy(b, 0, myAggragation,
                              myAggragateLength, len);
             myAggragateLength += len;
@@ -206,7 +215,7 @@
                 Trace.comm.verbosem("to=" + myRemoteAddr
                             + " addElement="+b.length);
             }
-            if (!myIsAggragating 
+            if (!myIsAggragating
                     || myAggragateLength + b.length+4 > myAggragation.length) {
                 flushElements();
                 if (b.length+4 > myAggragation.length) {
@@ -237,7 +246,7 @@
             flushElements();    // Write previous stuff under old rules
             AuthSecrets c = (AuthSecrets) elem;
             if (Trace.comm.debug && Trace.ON) {
-                Trace.comm.debugm("to=" + myRemoteAddr 
+                Trace.comm.debugm("to=" + myRemoteAddr
                                 + " doing ProtocolChange, protocolSuite="
                                 + c.myProtocolSuite);
             }
@@ -245,32 +254,33 @@
                 myIsAggragating = false;
                 myIsDoingMac = false;
             // begin daffE -> E
-            } else if (StartUpProtocol.PROTO_3DES_SDH_M.equals(c.myProtocolSuite)) {
+            } else if (StartUpProtocol.PROTO_3DES_SDH_M
+                       .equals(c.myProtocolSuite)) {
                 myIsAggragating = true;
                 myIsDoingMac = true;
-                myMacKey = c.myMacKey;
+                myMACKey = c.myMacKey;
                 myMacLen = 20;
                 byte[] raw_3des_key = TripleDESKeyConstructor.make(c.myDHSecret);
-                // myTransform = new TripleDESMsgEncryptor(c.myOutgoingSequence, raw_3des_key, true);
-                myTransform = new Encrypt3DES(raw_3des_key, c.myOutgoingSequence);
+                myTransform = 
+                    new Encrypt3DES(raw_3des_key, c.myOutgoingSequence, false);
                 mySequence = null;
                 setSHA1();
             // end daffE -> E
-            } else if (StartUpProtocol.PROTO_AUTH_SDH_M.equals(c.myProtocolSuite)) {
+            // Begin improved E protocol
+            } else if (StartUpProtocol.PROTO_3DES_SDH_M2
+                       .equals(c.myProtocolSuite)) {
                 myIsAggragating = true;
                 myIsDoingMac = true;
-                myMacKey = c.myMacKey;
+                myMACKey = c.myMacKey;
                 myMacLen = 20;
-                myTransform = null;
-                mySequence = c.myOutgoingSequence;
-                setSHA1();
-            } else if (StartUpProtocol.PROTO_NONE_SDH_M.equals(c.myProtocolSuite)) {
-                myIsAggragating = true;
-                myIsDoingMac = true;
-                myMacKey = c.myMacKey;
-                myMacLen = 20;
-                myTransform = null;
+                myIsDoingHMAC = true;
+                byte[] raw_3des_key = TripleDESKeyConstructor.make(c.myDHSecret);
+                myTransform = new Encrypt3DES(raw_3des_key, c.myOutgoingSequence, true);
+                myTransform.init();
+                myIsStandardCBC = true;
+                mySequence = new byte[4]; // Assume initialized to zero
                 setSHA1();
+            // end improved E protocol
             }  else {
                 throw new IOException(
                         "Invalid protocol suite type "+c.myProtocolSuite);
@@ -281,14 +291,14 @@
     /**
      * Call a method in our DataPath
      *
-     * @param thunk a Thunk that will perform the call.  The thunk will 
+     * @param thunk a Thunk that will perform the call.  The thunk will
      * be called after the Vat lock is obtained.
      */
     private void callDataPath(DataCommThunk thunk) {
         try {
             myRunner.now(thunk);
         } catch(Throwable t) {
-            Trace.comm.errorm("to=" + myRemoteAddr + " Error while calling " 
+            Trace.comm.errorm("to=" + myRemoteAddr + " Error while calling "
                         + thunk, t);
             if (t instanceof VirtualMachineError) throw (VirtualMachineError)t;
             if (t instanceof ThreadDeath) throw (ThreadDeath)t;
@@ -298,12 +308,21 @@
     private byte[] computeMAC(byte[] b, int off, int len,
                               /*NilOK*/byte[] lenField) {
         if (Trace.comm.verbose && Trace.ON) {
-            Trace.comm.verbosem("to=" + myRemoteAddr 
+            Trace.comm.verbosem("to=" + myRemoteAddr
                     + " Calculating MAC on (length "+len+"):"
                     + HexStringUtils.byteArrayToReadableHexString(b, off, len));
         }
         mySHA1.reset();                 //Initialize a new hash
-        mySHA1.update(myMacKey);            // The MAC key
+        if (myIsDoingHMAC) {
+            /* Calculate sha1(key ^ ipad || data) */
+            byte[] pad = new byte[HASH_BLOCK_SIZE];
+            replicate(pad, (byte)0x36);
+            xor(pad, myMACKey);
+            mySHA1.reset();
+            mySHA1.update(pad);
+        } else {
+            mySHA1.update(myMACKey);            // The MAC key
+        }
         if (null != mySequence) {
             mySHA1.update(mySequence);
             increment(mySequence);
@@ -312,7 +331,19 @@
             mySHA1.update(lenField);
         }
         mySHA1.update(b, off, len);
-        return mySHA1.digest(myMacKey);     // The MAC key again
+        if (myIsDoingHMAC) {
+            byte[] hash = mySHA1.digest();
+
+            /* Calculate sha1(key ^ opad || hash */
+            byte[] pad = new byte[HASH_BLOCK_SIZE];
+            replicate(pad, (byte)0x5c);
+            xor(pad, myMACKey);
+            mySHA1.update(pad);
+            mySHA1.update(hash);
+            return mySHA1.digest();
+        } else {
+            return mySHA1.digest(myMACKey);     // The MAC key again
+        }
     }
     private void flushElements() throws IOException {
         if (Trace.comm.verbose && Trace.ON) {
@@ -348,12 +379,39 @@
             return mySequence;
         }
     }
-    private void increment(byte[] value) { 
+    private void increment(byte[] value) {
         for (int i=value.length-1; i>=0; i--) {
             byte v = (value[i] += 1);
             if (0 != v) break;
         }
     }
+
+  /**
+   * xor - Exclusive OR two byte arrays.
+   *
+   * @param a is the input and output array.
+   * @param b is the array which is XORed with a.
+   */
+  static private void xor(byte[] a, byte[] b) {
+    int len = Math.min(a.length, b.length);
+    for (int i=0; i<len; i++) {
+      a[i] ^= b[i];
+    }
+  }
+
+
+  /**
+   * replicate - Copy a single byte to all elements of a byte array.
+   *
+   * @param a is the byte array.
+   * @param v is the byte to be replicated.
+   */
+  static private void replicate(byte[] a, byte v) {
+    for (int i=0; i<a.length; i++) {
+      a[i] = v;
+    }
+  }
+
   /**
    * Calculate the MD5 hash of some data with a specific padding.
    * <p>
@@ -375,7 +433,18 @@
         md5.update(mdConst);
         return md5.digest(data);
     }
-    static /*package*/ int msgLength(int len, byte[] buf, 
+
+  /**
+   * Calculate the message length field for a message.
+   *
+   * @param len is the length of the message to have it's length encoded.
+   * @param buf is the output buffer for the encoded length.
+   * @param off is the offset in the buffer for where to place the encoded length.
+   * @param comprssed is true if compressed lengths are to be used.
+   *
+   * @return is the offset of the byte after the end of the length.
+   */
+    static /*package*/ int msgLength(int len, byte[] buf,
                                      int off, boolean compressed)
             throws IOException {
         if (compressed) {
@@ -400,6 +469,7 @@
         }
         return off;
     }
+
     /**
      * Inform the DataPath about a problem
      */
@@ -409,18 +479,17 @@
     /**
      * Body of the thread.  Responsible for dequeueing messages and
      * writing them.  Also for dequeueing parameter change orders (e.g.
-     * authentication changes) and executing them in order.  
+     * authentication changes) and executing them in order.
      * Calls DataPath.shutdown() before exiting.
      * Will exit if a null is dequeued.
      */
-     public void run() {
-// First build the connection.
+     public void run() { // First build the connection.
 
         try {
             NetAddr remoteNetAddr;
             if (null == mySocket) {
                 if (Trace.comm.debug && Trace.ON) {
-                    Trace.comm.debugm("Attempting outgoing connection to " 
+                    Trace.comm.debugm("Attempting outgoing connection to "
                                                 + myRemoteAddr);
                 }
                 long startTime = 0;
@@ -428,9 +497,9 @@
                     startTime = MicroTime.queryTimer();
                 }
                 remoteNetAddr = new NetAddr(myRemoteAddr);
-                //it's safe to not check optInetAddress() for null, since 
+                //it's safe to not check optInetAddress() for null, since
                 //remoteNetAddr must explicitly have one
-                InetAddress remoteInetAddress 
+                InetAddress remoteInetAddress
                         = remoteNetAddr.optInetAddress();
                 if (null != myAddressesTried.get(remoteInetAddress)) {
                     throw new NoRouteToHostException("Already failed once");
@@ -456,9 +525,9 @@
             }
             myLocalAddr = new NetAddr(mySocket.getLocalAddress(),
                                       mySocket.getLocalPort());
-            
+
             if (Trace.comm.debug && Trace.ON) {
-                Trace.comm.debugm("Acquired outgoing connection to " 
+                Trace.comm.debugm("Acquired outgoing connection to "
                             + myRemoteAddr + " from " + myLocalAddr);
             }
             try {
@@ -470,16 +539,16 @@
             }
             myOutputStream = mySocket.getOutputStream();
 
-            RecvThread receiver = new RecvThread(mySocket.getInputStream(), 
+            RecvThread receiver = new RecvThread(mySocket.getInputStream(),
                                                  myDataPath,
                                                  myRemoteAddr,
                                                  myRunner);
             callDataPath(
-                    new DataCommThunk(myDataPath, 
+                    new DataCommThunk(myDataPath,
                                       receiver,
                                       remoteNetAddr,
                                       myLocalAddr));
-                        
+
         } catch (Exception e) {
             if (e instanceof IOException) {
                 Trace.comm.eventm("IOException", e);
@@ -520,9 +589,9 @@
             }
             flushElements();    // Flush out last queued elements
             myOutputStream.flush();
-            
+
             if (Trace.comm.debug && Trace.ON) {
-                Trace.comm.debugm("to=" + myRemoteAddr 
+                Trace.comm.debugm("to=" + myRemoteAddr
                             + " I've been asked to shutdown");
             }
         } catch (Exception e) {
@@ -542,12 +611,12 @@
             Trace.comm.debugm("to=" + myRemoteAddr + " terminated");
         }
         //Notify the DataPath that the connection has shut down
-        if (null == shutDownReason) shutDownReason 
+        if (null == shutDownReason) shutDownReason
                 = new ConnectionShutDownException("Normal Shutdown");
         callDataPath(new DataCommThunk(myDataPath, getSequence(), shutDownReason));
         myDataPath = null;  // Help GC keep our secrets
         myTransform = null;
-        myMacKey = null;
+        myMACKey = null;
         mySHA1 = null;
     }
     /**
@@ -574,11 +643,11 @@
                 lineLen += lenField.length;
             }
             if (Trace.comm.event && Trace.ON) {
-                Trace.comm.eventm("to=" + myRemoteAddr 
+                Trace.comm.eventm("to=" + myRemoteAddr
                             + " Sending message len=" + len);
             }
             writeAndRecordProgress(b, off, len);
-            callDataPath(new DataCommThunk(myDataPath, 
+            callDataPath(new DataCommThunk(myDataPath,
                                            myAggragationCount,
                                            len,
                                            null));
@@ -591,13 +660,16 @@
         if (Trace.comm.timing && Trace.ON) startTime = MicroTime.queryTimer();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         baos.write(new byte[myMacLen+4]); // Write space for length + MAC
+        if (null != mySequence) {
+        	baos.write(mySequence);   // Write separate message sequence number
+        }
         if (null != lenField) {
             baos.write(lenField);
         }
         baos.write(b, off, len);
         baos.close();
         // Get the length and the length of the sent length field
-        int commLength = baos.size() - 24;
+        int commLength = baos.size() - 24 - mySequence.length;
 
         int offset = -1;
         if (commLength < 128) {
@@ -610,10 +682,10 @@
             throw new IOException("Packet too large: " + commLength
                     + " >= 2,097,152");
         }
-        // If not a multiple of 64 bits (8 bytes), pad for authentication
-        if ( (myIsCompressingMsgLengths || null != myTransform) 
-                && 0 != ((commLength-offset) & 7)) {
-            byte[] fill = new byte[8 - ((commLength-offset)&7)];
+        // If not a multiple of 64 bits (8 bytes), pad to 8 bytes
+        if ( (myIsCompressingMsgLengths || null != myTransform)
+                && 0 != ((baos.size()-offset) & 7)) {
+            byte[] fill = new byte[8 - ((baos.size()-offset)&7)];
             baos.write(fill);     // Pad to multiple of 8 bytes
         }
         byte[] data = baos.toByteArray();
@@ -651,12 +723,14 @@
         if (null != myTransform) {
             if (Trace.comm.timing && Trace.ON) startTime = MicroTime.queryTimer();
             if (Trace.comm.verbose && Trace.ON) {
-                Trace.comm.verbosem("to=" + myRemoteAddr + " authenticating " 
+                Trace.comm.verbosem("to=" + myRemoteAddr + " authenticating "
                         + (data.length-offset) + " bytes: "
-                        + HexStringUtils.byteArrayToReadableHexString(data, 
+                        + HexStringUtils.byteArrayToReadableHexString(data,
                                         offset, data.length-offset));
+            }
+            if (!myIsStandardCBC) {
+                myTransform.init();
             }
-            myTransform.init();
             myTransform.transform(data, offset, data.length-offset);
             if (Trace.comm.timing && Trace.ON) {
                 authenticationTime += MicroTime.queryTimer() - startTime;
@@ -684,6 +758,12 @@
                                        null));
         return;
     }
+
+    /**
+     * Send an aggrating mode message with only a single element in the message.
+     *
+     * @param b is the byte array which is the data of the message
+     */
     private void sendBytesWithLength(byte[] b) throws IOException {
 
         if (Trace.comm.verbose && Trace.ON) {
@@ -698,11 +778,15 @@
 
         sendBytes(b, 0, b.length, clen, b.length);
     }
+
+    /**
+     * Get an instance of the SHA1 message digest.
+     */
     private void setSHA1() {
         try {
             mySHA1 = MessageDigest.getInstance("SHA");
         } catch(NoSuchAlgorithmException e) {
-            Trace.comm.errorm("to=" + myRemoteAddr 
+            Trace.comm.errorm("to=" + myRemoteAddr
                         + " Unable to build SHA", e);
             Trace.comm.notifyFatal();
         }
@@ -711,8 +795,8 @@
      * Write a message in chunks and inform the datapath of progress in the
      * write.
      */
-    
-    private void writeAndRecordProgress(byte[] b, int off, int len) 
+
+    private void writeAndRecordProgress(byte[] b, int off, int len)
             throws IOException {
         int offset = off;
         while (0 != len) {
@@ -724,3 +808,4 @@
         }
     }
 }
+



1.2       +144 -174  e/src/jsrc/net/vattp/data/StartUpProtocol.java

Index: StartUpProtocol.java
===================================================================
RCS file: /cvs/e/src/jsrc/net/vattp/data/StartUpProtocol.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- StartUpProtocol.java	2000/12/21 22:15:18	1.1
+++ StartUpProtocol.java	2001/08/25 19:54:01	1.2
@@ -72,60 +72,59 @@
      * States for the connection startup state machine.  Current state
      * is in myState below.
      */
-    final /*package*/ static int ST_UNSTARTED                 = 0;
-    final /*package*/ static int ST_INCOMING_EXPECT_IWANT     = 1;
-    final /*package*/ static int ST_OUTGOING_EXPECT_IAM       = 2;
-    final /*package*/ static int ST_INCOMING_EXPECT_GIVEINFO  = 3;
-    final /*package*/ static int ST_OUTGOING_EXPECT_REPLYINFO = 4;
-    final /*package*/ static int ST_INCOMING_EXPECT_GO        = 5;
-    final /*package*/ static int ST_OUTGOING_EXPECT_GOTOO     = 6;
-    final /*package*/ static int ST_EXPECT_MESSAGE            = 7;
-    final /*package*/ static int ST_DEAD                      = 8;
-    final /*package*/ static int ST_TRY_NEXT                  = 9;
+    static /*package*/ final int ST_UNSTARTED                 = 0;
+    static /*package*/ final int ST_INCOMING_EXPECT_IWANT     = 1;
+    static /*package*/ final int ST_OUTGOING_EXPECT_IAM       = 2;
+    static /*package*/ final int ST_INCOMING_EXPECT_GIVEINFO  = 3;
+    static /*package*/ final int ST_OUTGOING_EXPECT_REPLYINFO = 4;
+    static /*package*/ final int ST_INCOMING_EXPECT_GO        = 5;
+    static /*package*/ final int ST_OUTGOING_EXPECT_GOTOO     = 6;
+    static /*package*/ final int ST_EXPECT_MESSAGE            = 7;
+    static /*package*/ final int ST_DEAD                      = 8;
+    static /*package*/ final int ST_TRY_NEXT                  = 9;
 
 
     /*
      * Tokens used for submessage types of the Msg.STARTUP message
      */
-    final private static byte TOK_BYE                =  1;
-    final private static byte TOK_DUP                =  2;
-    final private static byte TOK_GIVEINFO           =  3;
-    final private static byte TOK_GO                 =  4;
-    final private static byte TOK_GOTOO              =  5;
-    final private static byte TOK_IAM                =  6;
-    final private static byte TOK_IWANT              =  7;
-    final private static byte TOK_NOT_ME             =  8;
-    final private static byte TOK_REPLYINFO          =  9;
-    final private static byte TOK_TRY                = 10;
-    final private static byte TOK_RESUME             = 11;
-    final private static byte TOK_YOUCHOSE           = 12;
+    static private final byte TOK_BYE                =  1;
+    static private final byte TOK_DUP                =  2;
+    static private final byte TOK_GIVEINFO           =  3;
+    static private final byte TOK_GO                 =  4;
+    static private final byte TOK_GOTOO              =  5;
+    static private final byte TOK_IAM                =  6;
+    static private final byte TOK_IWANT              =  7;
+    static private final byte TOK_NOT_ME             =  8;
+    static private final byte TOK_REPLYINFO          =  9;
+    static private final byte TOK_TRY                = 10;
+    static private final byte TOK_RESUME             = 11;
+    static private final byte TOK_YOUCHOSE           = 12;
 
     /* Tokens used to report errors to the remote end.
      * All are negative numbers.
      */
-    final private static byte TOK_ERR_PROTOCOL       = -2;
-    final private static byte TOK_ERR_WRONG_ID       = -3;
-    final private static byte TOK_ERR_INTERNAL       = -4;
+    static private final byte TOK_ERR_PROTOCOL       = -2;
+    static private final byte TOK_ERR_WRONG_ID       = -3;
+    static private final byte TOK_ERR_INTERNAL       = -4;
  
      /*
      * Values for supported protocol suites:
      */
-    final /*package*/ static String PROTO_NONE             = "None";
-    final /*package*/ static String PROTO_3DES_SDH_M       = "3DES_SDH_M";
-    final /*package*/ static String PROTO_BLOWFISH56_SDH_M = "BLOWFISH56_SDH_M";
-    final /*package*/ static String PROTO_NONE_SDH_M       = "NONE_SDH_M";
-    final /*package*/ static String PROTO_AUTH_SDH_M       = "AUTH_SDH_M";
+    static /*package*/ final String PROTO_NONE             = "None";
+    static /*package*/ final String PROTO_3DES_SDH_M       = "3DES_SDH_M";
+    static /*package*/ final String PROTO_3DES_SDH_M2      = "3DES_SDH_M2";
 
     /** The protocol negotiation string we send, least desired last */
-    private static String TheAuthProtocols;
-    
-    /** The authentication protocols we support.  Excludes none which is a 
+    static private String TheAuthProtocols;
+
+    /** The authentication protocols we support.  Excludes none which is a
      * special case */
-    private static String[] TheAuthProtocolTable;
+    static private String[] TheAuthProtocolTable;
 
     static {
         TheAuthProtocols = "";
-        TheAuthProtocols += PROTO_3DES_SDH_M;  // daffE -> E
+        TheAuthProtocols += PROTO_3DES_SDH_M2 + ",";  // Improved protocol
+        TheAuthProtocols += PROTO_3DES_SDH_M;         // daffE -> E
         //'Nothin ain't worth 'nothing, but it's exportable :-)
 // daffE -> E       TheAuthProtocols += PROTO_AUTH_SDH_M + ",";
         //Compatibility with non-sequence checking versions.
@@ -149,16 +148,16 @@
             start = end + 1;
         }
         result[count-1] = TheAuthProtocols.substring(start);
-        
+
         TheAuthProtocolTable = result;
     }
 
     static public String[] authProtocolTable() {
         return TheAuthProtocolTable;
     }
-                    
+
     /* String names for the Tokens for use in trace messages */
-    final private static String[] tokNames = {
+    static private final String[] tokNames = {
         "TOK_BYE",
         "TOK_DUP",
         "TOK_GIVEINFO",
@@ -173,7 +172,7 @@
         "TOK_YOUCHOSE"
     };
 
-    final private static String[] errTokNames = {
+    static private final String[] errTokNames = {
         "***Unassigned***",
         "TOK_ERR_PROTOCOL",
         "TOK_ERR_WRONG_ID",
@@ -187,20 +186,20 @@
     /** Whether we are build for initiating an outbound connection or
      * responding to a remote connection */
     private boolean myIsIncoming;
-    
+
     /** The remote vatID we are communicating with */
     private String myRemoteVatID;
-    
-    /** The suspend ID to present to the other end for a reconnect.  
+
+    /** The suspend ID to present to the other end for a reconnect.
         If it is null, reconnection will not be attempted.
         (Outbound connections only)*/
     private /*nullOK*/ byte[] myOutgoingSuspendID;
-    
+
     /** The public key of the remote end */
     private PublicKey myHisPublicKey;
-    
+
     private KeyPair myIdentityKeys;
-    
+
     /** Entity from which to lookup foreign vatIDs */
     private VatLocationLookup myVLS;
 
@@ -213,17 +212,17 @@
     /** Current state of the startup protocol state machine */
     private int myState = ST_UNSTARTED;
 
-    /** Set true if we should stop attempting to make a connection 
+    /** Set true if we should stop attempting to make a connection
         before outgoingSetup has been called.*/
     private boolean myStop = false;
-    
+
     /** The agreed E message protocol version */
     private String myEMsgProtocolVersion;
-    
+
     /** The agreed upon protocol suite */
     private String myProtocolSuite;
-    
-    
+
+
     /** The Signature object used for signing and checking signatures */
     //WARNING - WARNING - WARNING
     // In order to use ESecureRandom to calculate each signature in mySignature
@@ -233,12 +232,12 @@
     // I (WSF) think it will be easier to avoid this problem if mySignature
     // remains private, and signatures are only calculated one place in the code.
     private Signature mySignature;
-    
-    
+
+
     /** Messages I've sent which are to be signed for as part of end point
      * authentication. */
     private Vector myMessagesToSign = new Vector(5);
-    
+
     /** Messages I've received whose signature is to be checked as part of
      * end point identification. */
     private Vector hisMessagesToSign = new Vector(5);
@@ -275,12 +274,12 @@
      * @param localFlattenedSearchPath the search path we publish for others
      *        looking for the local vat in semicolon separated form.
      */
-    /*package*/ StartUpProtocol(DataPath path, 
+    /*package*/ StartUpProtocol(DataPath path,
                                 boolean isIncoming,
-                                String /*nullOK*/ remoteVatID, 
+                                String /*nullOK*/ remoteVatID,
                                 KeyPair identityKeys,
                                 String localVatID,
-                                byte[] /*nullOK*/ outgoingSuspendID, 
+                                byte[] /*nullOK*/ outgoingSuspendID,
                                 String localFlattenedSearchPath,
                                 VatLocationLookup vls)
     {
@@ -288,17 +287,17 @@
         myIsIncoming = isIncoming;
         myIdentityKeys = identityKeys;
         myLocalFlattenedSearchPath = localFlattenedSearchPath;
-        
+
         myVLS = vls;
 
         myLocalVatID = localVatID;
-                        
+
         //Register for the startup message types
         try {
             myDataPath.registerMsgHandler(Msg.STARTUP, this);
             myDataPath.registerMsgHandler(Msg.PROTOCOL_VERSION, this);
             myDataPath.registerMsgHandler(Msg.PROTOCOL_ACCEPTED, this);
-            
+
             if (!myIsIncoming) {
                 myOutgoingSuspendID = outgoingSuspendID;
                 myRemoteVatID = remoteVatID;
@@ -323,11 +322,11 @@
             }
         }
     }
-// Protocol methods.  These methods are presented more or less in the order 
+// Protocol methods.  These methods are presented more or less in the order
 // they will be executed during the startup protocol.  Note that the methods
 // used by the initator of the connection are interleaved with the methods
 // used by the receiver of the connection.
-// 
+//
 // The whole process is started in the initator's constructor which sends
 // two messages, Msg.PROTOCOL_VERSION, and Msg.STARTUP + TOK_IWANT.
 
@@ -346,7 +345,7 @@
      *              remote end.
      */
 
-    void checkProtocolVersion(DataInputStream packetIn, byte[] packet) 
+    void checkProtocolVersion(DataInputStream packetIn, byte[] packet)
             throws IOException {
         hisMessagesToSign.addElement(packet);
         Vector versions = new Vector(10);   // To save their supported versions in case of error
@@ -394,35 +393,30 @@
         os.writeByte(Msg.PROTOCOL_ACCEPTED);
         os.writeUTF(protocol);
         sendMessageForSignature(baos.toByteArray());
-        
+
         myEMsgProtocolVersion = protocol;
         packetIn.close();
     }
-    
-    // Method from the MsgHandler interface.
+// Method from the MsgHandler interface.
     /**
      * Process a connection failure
      */
     public void connectionDead(DataConnection /*nullOK*/willBeNull, Throwable reason) {
         // Everything should be handled by the DataPath
     }
-    
-    /**
-     * Perform the first calculation in Diffie Hellman key exchange.
-     * <p>
-     * This method gets a random x and calculate g**x mod p.  Return the value
-     * as a String base 10.
-     *
-     * @return A byte array representing the result of the first Diffie
-     *         Hellman calculation.
-     */
+  /**
+   * Perform the first calculation in Diffie Hellman key exchange.
+   * <p>
+   * This method gets a random x and calculate g**x mod p.  Return the value
+   * as a String base 10.
+   *
+   * @return A byte array representing the result of the first Diffie
+   *         Hellman calculation.
+   */
+
     private byte[] firstDH() {
         long startTime = Trace.comm.timing ? MicroTime.queryTimer() : 0;
-
-        //MSM: should be passed in entropy as a capability
-        ESecureRandom entropy = ESecureRandom.getESecureRandom();
-
-        x = new BigInteger(256, entropy);
+        x = new BigInteger(256, ESecureRandom.getESecureRandom());
         byte[] ans = g.modPow(x,modulus).toByteArray();
         if (Trace.comm.timing && Trace.ON) {
             Trace.comm.timingm("FirstDiffieHellman time "
@@ -430,12 +424,11 @@
         }
         return ans;
     }
-    
     /**
      * Format a Msg.STARTUP packet for error messages.
      *
-     * @param packet the byte array which is the complete packet.
-     * @return the packet formated as a string.
+     *@param packet the byte array which is the complete packet.
+     *@return the packet formated as a string.
      */
     private String formatStartupPacket(byte[] packet) {
         String ret = "";
@@ -457,17 +450,16 @@
         }
         return ret + "\n" + HexStringUtils.byteArrayToReadableHexString(packet);
     }
-    
-    // Method for use by DataPath
+// Method for use by DataPath
     /**
      * Return the connection startup state
      *
      * @return The connection startup state code for debugging purposes.
      */
+
     /*package*/ int getState() {
         return myState;
     }
-    
     /**
      * Process expecting an GIVEINFO <remoteVatID> <remotePath> <hisPublicKey>
      *   -or-
@@ -484,7 +476,7 @@
      *            notifing the other end.
      */
     private void handleStateIncomingExpectGIVEINFO(byte token,
-                                                   DataInputStream packetIn, 
+                                                   DataInputStream packetIn,
                                                    byte[] packet)
          throws IOException
     {
@@ -526,16 +518,15 @@
             }
         } else if (token == TOK_DUP) {
             myDataPath.duplicatePath(
-                        "Incoming crossed connections" 
+                        "Incoming crossed connections"
                         + formatStartupPacket(packet), false);
         } else if (token == TOK_NOT_ME) {
             startupLocalError("Other end tried to connect to self");
         } else {
-            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_GIVEINFO) 
+            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_GIVEINFO)
                             + " got " + formatStartupPacket(packet));
         }
     }
-    
     /**
      * Process expecting a GO <auth suite> <DH parameter>
      *   -or-
@@ -565,7 +556,7 @@
                     packetIn.read(publicDH);
                     byte[] sig = new byte[packetIn.readUnsignedShort()];
                     packetIn.read(sig);
-                    
+
                     byte[] dhparm = firstDH();
                     myProtocolSuite = protocol;
                     if (!isSecondDHOK(publicDH, sig, token)) {
@@ -601,11 +592,10 @@
                         "Incoming crossed connections "
                         + formatStartupPacket(packet), true);
         } else {
-            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_GO) 
+            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_GO)
                     + " got " + formatStartupPacket(packet));
         }
     }
-    
     /**
      * Process expecting a IWANT <localVatID> message.
      *
@@ -622,32 +612,36 @@
         hisMessagesToSign.addElement(packet);
         if (myStop) {
             startupError(TOK_DUP, "Stopped connection");
+            return;
+        } 
+        if (token != TOK_IWANT) { /* IWANT <id> */
+            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_IWANT)
+                         + " got " + formatStartupPacket(packet));
             return;
-        } else if (token == TOK_IWANT) { /* IWANT <id> */
-            String[] locations;
-            String wantedVatID = packetIn.readUTF();
-            if (wantedVatID.equals(myLocalVatID) ||
-                   wantedVatID.equals(VatIdentity.WHOEVER)) {
-                sendIAm();
-                myState = ST_INCOMING_EXPECT_GIVEINFO;
-            } else if (myVLS != null &&
-                   (locations = myVLS.getLocations(wantedVatID)).length >= 1) {
+        }
+        String wantedVatID = packetIn.readUTF();
+        if (wantedVatID.equals(myLocalVatID) ||
+            wantedVatID.equals(VatIdentity.WHOEVER))
+        {
+            sendIAm();
+            myState = ST_INCOMING_EXPECT_GIVEINFO;
+            return;
+        }
+        if (myVLS != null) {
+            String[] locations = myVLS.getLocations(wantedVatID);
+            if (locations.length >= 1) {
+                //XXX future bug: only uses the first one
                 sendTry(locations[0]);
-                //XXX locations[any >= 1] not processed
                 myDataPath.tryNext("VLS lookup completed");
-            } else {
-                if (Trace.comm.debug && Trace.ON) {
-                    Trace.comm.debugm("got request for " + wantedVatID 
-                            + " when I am " + myLocalVatID);
-                }
-                startupError(TOK_NOT_ME, "I don't know " + wantedVatID);
+                return;
             }
-        } else {
-            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_IWANT) 
-                         + " got " + formatStartupPacket(packet));
         }
+        if (Trace.comm.debug && Trace.ON) {
+            Trace.comm.debugm("got request for " + wantedVatID
+                    + " when I am " + myLocalVatID);
+        }
+        startupError(TOK_NOT_ME, "I don't know " + wantedVatID);
     }
-    
     /*
      * GOTOO
      *   -or-
@@ -693,11 +687,10 @@
         } else if (token == TOK_BYE) {
             myDataPath.cantResume(formatStartupPacket(packet));
         } else {
-            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_GOTOO) 
+            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_GOTOO)
                     + " got " + formatStartupPacket(packet));
         }
     }
-    
     /**
      * Process expecting an IAM <remoteVatID> <myPublicKey>
      *   -or-
@@ -717,7 +710,7 @@
      *            is thrown if this MsgConnection should terminate without
      *            notifing the other end.
      */
-    private void handleStateOutgoingExpectIAM(byte token, 
+    private void handleStateOutgoingExpectIAM(byte token,
                 DataInputStream packetIn, byte[] packet)
             throws IOException {
         hisMessagesToSign.addElement(packet);
@@ -740,7 +733,7 @@
                 byte[] hisKey = new byte[packetIn.readUnsignedShort()];
                 packetIn.readFully(hisKey);
                 if (!isHisPublicKeyOK(remoteVatID, hisKey, token)) return;
-                
+
                 if (myRemoteVatID.equals(VatIdentity.WHOEVER)) {
                     myRemoteVatID = remoteVatID;
                     Object orders = myDataPath.identifyOutgoing(
@@ -775,11 +768,10 @@
                         "outgoing crossed connections"
                         + formatStartupPacket(packet), true);
         } else {
-            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_IAM) 
+            startupError(TOK_ERR_PROTOCOL, "Expected " + tokName(TOK_IAM)
                     + " got " + formatStartupPacket(packet));
         }
     }
-    
     /**
      * Process expecting a REPLYINFO <remotePath>
      *   -or-
@@ -812,7 +804,7 @@
                     startupError(TOK_DUP, "Crossed connections");
                     return;
             }
-            //ConstList path = EARL.parseSearchPath(remoteSearchPath);
+            //String[] path = EARL.parseSearchPath(remoteSearchPath);
             //myDataPath.extendSearchPath(path);
             myState = ST_OUTGOING_EXPECT_GOTOO;
             if (null != myOutgoingSuspendID) {
@@ -831,7 +823,7 @@
                 }
                 if (protocol.equals("")) {
                     //No agreement
-                    startupError(TOK_ERR_PROTOCOL, 
+                    startupError(TOK_ERR_PROTOCOL,
                                         "Can't agree on an authorization protocol");
                     return;
                 }
@@ -848,17 +840,16 @@
             }
         } else if (token == TOK_DUP) {
             myDataPath.duplicatePath(
-                        "Outgoing crossed connections " 
+                        "Outgoing crossed connections "
                         + formatStartupPacket(packet), true);
             return;
         } else {
-            startupError(TOK_ERR_PROTOCOL, "Expected " 
-                         + tokName(TOK_REPLYINFO) + " got " 
+            startupError(TOK_ERR_PROTOCOL, "Expected "
+                         + tokName(TOK_REPLYINFO) + " got "
                          + formatStartupPacket(packet));
             return;
         }
     }
-    
   /**
    * Decode the line form of his public key and check that it is for his
    * vatID.
@@ -891,7 +882,6 @@
         }
         return true;
     }
-    
   /**
    * Perform the second calculation in Diffie Hellman key exchange.
    * <p>
@@ -902,14 +892,14 @@
    * It then takes the resulting dh secret and calculates values for the
    * initial sequence numbers (both send path and receive path).
    *
-   * @param publiddh is a byte array containing the far end's first Diffie 
+   * @param publiddh is a byte array containing the far end's first Diffie
    *         Hellman calculation.
-   * @param sig is a byte array containing the far end's DSS signature on 
+   * @param sig is a byte array containing the far end's DSS signature on
    *         the startup protocol.
    * @param token The startup protocol token being processed.  (For determining
    *         whether we are the initator or receipent and error reporting.)
    *
-   * @return is true if the connection attempt should continue, 
+   * @return is true if the connection attempt should continue,
    *         false otherwise.
    */
 
@@ -948,13 +938,12 @@
         myDataPath.setAuthorizationSecrets(dhSecret, sendIV, recvIV);
         return true;
     }
-    
   /**
    * Check the signature on the data received.
    *
    * @param data is the data to check.
    * @param sig is the signature.
-   * @param token is the startup protocol token being processed for error 
+   * @param token is the startup protocol token being processed for error
    * reporting.
    *
    * @return is true if the signature is good.  False for a bunch of "can't
@@ -962,6 +951,7 @@
    * and things like invalid or no public key from the other end, or invalid
    * signature.
    */
+
     private boolean isSigGood(byte