[Webfunds-commits] java/webfunds/sox Crypto.java

Jeroen C. van Gelderen gelderen@cypherpunks.ai
Sat, 29 Jul 2000 23:59:59 -0400 (AST)


gelderen    00/07/29 23:59:59

  Modified:    webfunds/sox Crypto.java
  Log:
  Checkpoint.
  
  - Remove unused password-based encryption functions for now.
    They were insecure and needed be replaced anyway.
  - Same for secure checksum routines.
  - Use JCE KeyGenerator for TripleDES keys.
  - Add some basic debugging methods and calls. Will be improved upon.
  - Remove import of java.security.Cipher and change all uses of Cipher to
    use fully qualified class names. This is neccessary to prevent name
    clashes with JCE and will go away soon.
  - Load CryptixCrypto (JCE) provider dynamically.
  - Make generateKeys(...) synchronized because of potential race conditions.

Revision  Changes    Path
1.41      +80 -215   java/webfunds/sox/Crypto.java

Index: Crypto.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/sox/Crypto.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- Crypto.java	2000/07/29 17:15:33	1.40
+++ Crypto.java	2000/07/30 03:59:58	1.41
@@ -1,4 +1,4 @@
-/* $Id: Crypto.java,v 1.40 2000/07/29 17:15:33 gelderen Exp $
+/* $Id: Crypto.java,v 1.41 2000/07/30 03:59:58 gelderen Exp $
  *
  * Copyright (c) Systemics Inc. 1995-2000 on behalf of
  * The WebFunds Development Team.  All Rights Reserved.
@@ -8,12 +8,10 @@
 
 import java.io.*;
 import java.math.BigInteger;
-import java.security.Cipher;
 import java.security.GeneralSecurityException;
 import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.KeyException;
-import java.security.KeyGenerator;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.MessageDigest;
@@ -30,6 +28,8 @@
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
+import javax.crypto.KeyGenerator;
+
 import cryptix.provider.key.RawSecretKey;
 import cryptix.provider.rsa.RawRSAPrivateKey;
 import cryptix.provider.rsa.RawRSAPublicKey;
@@ -50,13 +50,24 @@
  *
  * Centralized crypto methods. Currently being overhauled.
  *
- * @version $Revision: 1.40 $
+ * @version $Revision: 1.41 $
  */
 public final class Crypto
 {
-    static
-    {
+
+// Debug helper methods
+//............................................................................
+
+    private static void logDebug(String s) {
+        System.err.println("Crypto: " + s);
+    }
+
+//............................................................................
+
+    static {
         java.security.Security.addProvider(new cryptix.provider.Cryptix());
+        java.security.Security.addProvider(
+            new cryptix.jce.provider.CryptixCrypto() );
     }
     
     
@@ -104,29 +115,31 @@
     }
 
 
+
+    private static KeyPairGenerator keyGen = null;
 
-    protected static KeyPairGenerator keyGen = null;
 
     /**
      * Useful for making accounts, better than certs.
      * Do this:
      *    PublicKey publicKey = keyPair.getPublic();
-     *    privateKey = keyPair.getPrivate();
+     *    PrivateKey privateKey = keyPair.getPrivate();
      */
-    public static KeyPair generateKeys(int bits)
+    public static synchronized KeyPair generateKeys(int bits)
     {
-        if (keyGen == null)
-        {
-            try {
+        logDebug("generateKeys(...)");
+        try {
+            if (keyGen == null)
                 keyGen = KeyPairGenerator.getInstance(pk_alg);
-            } catch (NoSuchAlgorithmException ex) {
-                throw new ProviderException(pk_alg+" Algorithm missing, " + ex);
-            }
-        }
 
-        keyGen.initialize(bits, getSecureRandom());
-        KeyPair keyPair = keyGen.generateKeyPair();
-        return keyPair;
+            keyGen.initialize(bits, getSecureRandom());
+            KeyPair keyPair = keyGen.generateKeyPair();
+            logDebug("generateKeys: returning " + keyPair);
+            return keyPair;
+
+        } catch (NoSuchAlgorithmException ex) {
+            throw new ProviderException(pk_alg+" Algorithm missing, " + ex);
+        }
     }
 
 
@@ -175,59 +188,26 @@
      * Generate (randomly) a new Key object,
      * suitable for the default symmetric cipher.
      *
+     * Uses JCE 1.2.
+     *
      * @return A new (random) Key object
      */
-    public static Key generateKey()
-        throws KeyException
-    {
-        try {
-            // if (sr == null)
-            //     sr = new SecureRandom();
-        
-            //
-            // This is the JCE 1.2 way of generating a symmetric key
-            //
-            KeyGenerator kg = KeyGenerator.getInstance(cipher_alg);
-            //      kg.init(getSecureRandom()); // JCE 1.2
-            kg.initialize(getSecureRandom()); // JCE 1.1
-            return kg.generateKey();
-        } catch (NoSuchAlgorithmException e) {
-            throw new ProviderException("Symmetric Algorithm (" + cipher_alg +
-                                        ") not found ("+ e.getMessage()+")");
-        }
-    }
+    public static Key generateKey() throws KeyException {
 
-   /**
-     * Turn a password into a key of <i>n</i> bytes,
-     * suitable for use with a symmetric cipher
-     * This is achieved by running the password through
-     * a message digest function, and using procrastean
-     * assignment to the return value.
-     * @param password the password being converted
-     * @return the key
-     */
-    public static Key password2key(String password)
-    {
-        MessageDigest md;
+        logDebug("generateKey() called");
         try {
-            md = MessageDigest.getInstance(md_alg);
-        }
-        catch (NoSuchAlgorithmException e) {
-            throw new InternalError("Badly installed JCE: missing Algorithm ("+
-                                    e.getMessage()+")");
-        }
-        md.update(password.getBytes());
-        byte[] digest = md.digest();
-        byte[] key = new byte[cipher_keylen];
-        int pos = 0;
-        while (pos < cipher_keylen) {
-            int count = digest.length;
-            if ((pos + count) > cipher_keylen)
-                count = cipher_keylen - pos;
-            System.arraycopy(digest, 0, key, pos, count);
-            pos += count;
+            KeyGenerator kg = 
+                KeyGenerator.getInstance("DESede", "CryptixCrypto");
+            kg.init(getSecureRandom()); // JCE 1.2
+            Key result = kg.generateKey();
+            logDebug(result.toString());
+            return result;
+
+        } catch (Exception e) {
+            throw new ProviderException(
+                "Symmetric Algorithm (DESede) not found (" +
+                e.getMessage() + ")" );
         }
-        return new RawSecretKey(cipher_alg, key);
     }
 
 
@@ -247,18 +227,17 @@
      * @param len the length of the data
      * @return the message digest (as a byte array)
      */
-    public static byte[] digest(byte[] data, int offset, int len)
-    {
-        MessageDigest md;
+    public static byte[] digest(byte[] data, int offset, int len) {
+
         try {
-            md = MessageDigest.getInstance(md_alg);
-        }
-        catch (NoSuchAlgorithmException e) {
+            MessageDigest md = MessageDigest.getInstance(md_alg);
+            md.update(data, offset, len);
+            return md.digest();
+
+        } catch (NoSuchAlgorithmException e) {
             throw new ProviderException("Message digest Algorithm ("+md_alg+
                                         ") missing ("+e.getMessage()+")");
         }
-        md.update(data, offset, len);
-        return md.digest();
     }
 
    /**
@@ -277,66 +256,6 @@
     }
 
 
-
-////////////////////////////////////////////////////////////////////////
-// Convenience methods for getting secure checksums of data
-////////////////////////////////////////////////////////////////////////
-
-   /**
-     * Create a secure checksum (as a byte array) from some data.
-     * This checksum can be used to "lock" some data, in order to
-     * prevent tampering.  This is achieved by saving this secure
-     * checksum along with the data, and in the future when the
-     * data is restored, the checksum should again be computed and
-     * compared with the stored checksum.  Without knowledge of the
-     * secret password, it is infeasible for the data to be modified
-     * and the checksum adjusted to hide the fact that the modification
-     * has taken place.
-     *
-     * @param password the secret with which to secure the checksum
-     * @param data the data to be checksummed
-     * @param offset the offset into the array of the start of the data
-     * @param len the length of the data
-     * @return the secure checksum (as a byte array)
-     */
-    public static byte[] checksum(String password, 
-                                  byte[] data, int offset, int len)
-    {
-        MessageDigest md;
-        try {
-            md = MessageDigest.getInstance(md_alg);
-        }
-        catch (NoSuchAlgorithmException e) {
-            throw new ProviderException("Message digest Algorithm ("+md_alg+
-                                        ") missing ("+e.getMessage()+")");
-        }
-        md.update(password.getBytes());
-        md.update(data, offset, len);
-        return md.digest();
-    }
-
-   /**
-     * Create a secure checksum (as a byte array) from some data.
-     * This checksum can be used to "lock" some data, in order to
-     * prevent tampering.  This is achieved by saving this secure
-     * checksum along with the data, and in the future when the
-     * data is restored, the checksum should again be computed and
-     * compared with the stored checksum.  Without knowledge of the
-     * secret password, it is infeasible for the data to be modified
-     * and the checksum adjusted to hide the fact that the modification
-     * has taken place.
-     *
-     * @param password the secret with which to secure the checksum
-     * @param data the data to be checksummed
-     * @return the secure checksum (as a byte array)
-     */
-    public static byte[] checksum(String password, byte[] data)
-    {
-        return checksum(password, data, 0, data.length);
-    }
-
-
-
 ////////////////////////////////////////////////////////////////////////
 // Convenience methods for symmetric cipher encrypting and decrypting
 ////////////////////////////////////////////////////////////////////////
@@ -353,12 +272,12 @@
      */
     public static byte[] encrypt(Key key, byte[] data, int offset, int len)
     {
-        
       try {
-        Cipher cipher = Cipher.getInstance(Cipher.getInstance(cipher_alg),
-                                    (Mode)Mode.getInstance(cipher_mode),
-                                    PaddingScheme.getInstance(cipher_padding)
-                                    );
+        java.security.Cipher cipher = 
+            java.security.Cipher.getInstance(
+                java.security.Cipher.getInstance(cipher_alg),
+                (Mode)Mode.getInstance(cipher_mode),
+                PaddingScheme.getInstance(cipher_padding) );
                                     
                                     
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -389,25 +308,7 @@
     }
     
 
-
-   /**
-     * Encrypt the data and return the encrypted binary data
-     * The data is compressed before encrypting
-     *
-     * @param password the password with which to encrypt the data
-     * @param data the data being encrypted (as a byte array)
-     * @param offset the offset within <i>data</i> from which to start
-     * @param len the length of the data with the <i>data</i> array
-     * @return the encrypted data
-     */
-    public static byte[] encrypt(String password, 
-                                 byte[] data, int offset, int len)
-    {
-      return encrypt(password2key(password), data, offset, len);
-    }
-
-
-   /**
+    /**
      * Encrypt the data and return the encrypted binary data
      * The data is compressed before encrypting
      *
@@ -420,20 +321,7 @@
       return encrypt(key, data, 0, data.length);
     }
 
-   /**
-     * Encrypt the data and return the encrypted binary data
-     * The data is compressed before encrypting
-     *
-     * @param password the password with which to encrypt the data
-     * @param data the data being encrypted (as a byte array)
-     * @return the encrypted data
-     */
-    public static byte[] encrypt(String password, byte[] data)
-    {
-      return encrypt(password2key(password), data, 0, data.length);
-    }
     
-    
    /**
      * Decrypt the data and return the decrypted binary data
      * The data is decompressed after decrypting
@@ -448,14 +336,13 @@
     public static byte[] decrypt(Key key, byte[] data, int offset, int len)
         throws KeyException
     {
-        
-        try
-        {
-           
-            Cipher cipher = Cipher.getInstance(Cipher.getInstance(cipher_alg),
-                                    (Mode)Mode.getInstance(cipher_mode),
-                                    PaddingScheme.getInstance(cipher_padding)
-                                    );
+        try {
+            java.security.Cipher cipher = 
+                java.security.Cipher.getInstance(
+                    java.security.Cipher.getInstance(cipher_alg),
+                    (Mode)Mode.getInstance(cipher_mode),
+                    PaddingScheme.getInstance(cipher_padding) );
+
             cipher.initDecrypt(key);
             
             int zippedLen = cipher.doFinal(data, offset, len, data, 0);
@@ -489,22 +376,6 @@
         }
     }
 
-   /**
-     * Decrypt the data and return the encrypted binary data
-     * The data is uncompressed after decrypting
-     *
-     * @param password the password with which to decrypt the data
-     * @param data the data being decrypted (as a byte array)
-     * @param offset the offset within <i>data</i> from which to start
-     * @param len the length of the data with the <i>data</i> array
-     * @return the decrypted data
-     */
-    public static byte[] decrypt(String password, 
-                                 byte[] data, int offset, int len)
-        throws KeyException
-    {
-      return decrypt(password2key(password), data, offset, len);
-    }
 
    /**
      * Decrypt the data and return the encrypted binary data
@@ -520,22 +391,7 @@
       return decrypt(key, data, 0, data.length);
     }
 
-   /**
-     * Decrypt the data and return the encrypted binary data
-     * The data is uncompressed after decrypting
-     *
-     * @param password the password with which to decrypt the data
-     * @param data the data being decrypted (as a byte array)
-     * @return the decrypted data
-     */
-    public static byte[] decrypt(String password, byte[] data)
-        throws KeyException
-    {
-      return decrypt(password2key(password), data);
-    }
-
 
-
 ////////////////////////////////////////////////////////////////////////
 // Convenience methods for asymmetric cipher encrypting and decrypting
 ////////////////////////////////////////////////////////////////////////
@@ -560,7 +416,8 @@
         // if (sr == null)
         //    sr = new SecureRandom();
         
-        Cipher rsa = Cipher.getInstance(pk_alg);
+        java.security.Cipher rsa = 
+            java.security.Cipher.getInstance(pk_alg);
         pk = toCryptixKey(pk);
         rsa.initEncrypt(pk);
 
@@ -691,7 +548,8 @@
         //
         // Decrypt the key
         //
-        Cipher rsa = Cipher.getInstance(pk_alg);
+        java.security.Cipher rsa = 
+            java.security.Cipher.getInstance(pk_alg);
         rsa.initDecrypt(pk);
 
         int pktlen = rsa.getCiphertextBlockSize() + 1;
@@ -751,7 +609,8 @@
     {
       try {
         // Only using cipher to get packet length ...
-        Cipher rsa = Cipher.getInstance(pk_alg);
+        java.security.Cipher rsa = 
+            java.security.Cipher.getInstance(pk_alg);
         rsa.initDecrypt(pk);
         int pktlen = rsa.getCiphertextBlockSize();
         return decrypt(key, data, offset+pktlen, len-pktlen);
@@ -1256,8 +1115,14 @@
     }
 
 
-    // XXX: move out of Certificate.java. Can go for JCE 1.2
+    /**
+     * Convert the given key to a Cryptix' RawRSAPublicKey.
+     *
+     * <p>This is a no-op when the given key already is RawRSAPublicKey.</p>
+     */
     private static PublicKey toCryptixKey(PublicKey pk) {
+
+        // XXX: move out of Certificate.java. Can go for JCE 1.2
 
         /*
          * Don't do conversion when the key is a Cryptix RAW-encoded key.