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

Jeroen C. van Gelderen gelderen@cypherpunks.ai
Wed, 2 Aug 2000 20:59:18 -0400 (AST)


gelderen    00/08/02 20:59:17

  Modified:    webfunds/sox Crypto.java
  Log:
  - Use JCE 1.2 keygen with the old RSA encrypt/decrypt routines.
  - Cleanup.
  
  I won't write more commit messages until I'm done with this file :-)

Revision  Changes    Path
1.45      +166 -185  java/webfunds/sox/Crypto.java

Index: Crypto.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/sox/Crypto.java,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- Crypto.java	2000/07/31 18:07:14	1.44
+++ Crypto.java	2000/08/03 00:59:17	1.45
@@ -1,4 +1,4 @@
-/* $Id: Crypto.java,v 1.44 2000/07/31 18:07:14 gelderen Exp $
+/* $Id: Crypto.java,v 1.45 2000/08/03 00:59:17 gelderen Exp $
  *
  * Copyright (c) Systemics Inc. 1995-2000 on behalf of
  * The WebFunds Development Team.  All Rights Reserved.
@@ -16,16 +16,17 @@
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.MessageDigest;
-import java.security.Mode;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
-import java.security.PaddingScheme;
 import java.security.PrivateKey;
 import java.security.ProviderException;
 import java.security.PublicKey;
 import java.security.SecureRandom;
+import java.security.Signature;
 import java.security.SignatureException;
 import java.security.cert.Certificate;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPublicKey;
 import java.util.Date;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
@@ -57,7 +58,7 @@
  *
  * Centralized crypto methods. Currently being overhauled.
  *
- * @version $Revision: 1.44 $
+ * @version $Revision: 1.45 $
  */
 public final class Crypto
 {
@@ -78,22 +79,19 @@
     }
     
     
-    //
-    // The default algorithms and the like, which should
-    // be overriden at start-up time if desired.
-    //
-    public static String md_alg = "SHA";
-    public static String cipher_alg = "DES-EDE3";
+    private static String 
+        CIPHER_ALGORITHM = "DESede",
+        CIPHER_TRANSFORM = "DESede/CBC/PKCS#5",
+        MD_ALGORITHM     = "SHA";
+
     public static int cipher_keylen = 24;
-    public static String cipher_mode = "CBC";
-    public static String cipher_padding = "PKCS#5";
     public static String pk_alg = "RSA";
-    public static int pk_strength = 384; // Testing
     public static String sig_alg = "MD5/RSA";
-    public static int cert_validity = 365 * 24 * 60 * 60;  // a year
-    public static boolean quiet = true;
+
+
     public static SecureRandom sr;
 
+
     /**
      * set a PRNG.  Sometimes the default is not good enough.
      */
@@ -123,6 +121,9 @@
 
 
 
+    /**
+     * Global key pair generator. Used by (synchronized) generateKeys only.
+     */
     private static KeyPairGenerator keyGen = null;
 
 
@@ -137,15 +138,18 @@
         logDebug("generateKeys(...)");
         try {
             if (keyGen == null)
-                keyGen = KeyPairGenerator.getInstance(pk_alg);
+                keyGen = KeyPairGenerator.getInstance(pk_alg, "CryptixCrypto");
 
             keyGen.initialize(bits, getSecureRandom());
             KeyPair keyPair = keyGen.generateKeyPair();
             logDebug("generateKeys: returning " + keyPair);
             return keyPair;
 
-        } catch (NoSuchAlgorithmException ex) {
+        } catch(NoSuchAlgorithmException ex) {
             throw new ProviderException(pk_alg+" Algorithm missing, " + ex);
+
+        } catch(NoSuchProviderException e) {
+            throw new ProviderException();
         }
     }
 
@@ -204,15 +208,15 @@
         logDebug("generateKey() called");
         try {
             KeyGenerator kg = 
-                KeyGenerator.getInstance("DESede", "CryptixCrypto");
-            kg.init(getSecureRandom()); // JCE 1.2
+                KeyGenerator.getInstance(CIPHER_ALGORITHM, "CryptixCrypto");
+            kg.init(getSecureRandom());
             Key result = kg.generateKey();
             logDebug(result.toString());
             return result;
 
         } catch (Exception e) {
             throw new ProviderException(
-                "Symmetric Algorithm (DESede) not found (" +
+                "Symmetric Algorithm (" + CIPHER_ALGORITHM +") not found (" +
                 e.getMessage() + ")" );
         }
     }
@@ -227,23 +231,23 @@
      * data (as a byte array)
      * The digest uses the algorithm specified in 
      * crypto.message-digest.algorithm,
-     * and if not defined, defaults to the md_alg algorithm.
+     * and if not defined, defaults to the MD_ALGORITHM algorithm.
      *
      * @param data the data to be digested
      * @param offset the offset into the array of the start of the data
      * @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) {
+    private static byte[] digest(byte[] data, int offset, int len) {
 
         try {
-            MessageDigest md = MessageDigest.getInstance(md_alg);
+            MessageDigest md = MessageDigest.getInstance(MD_ALGORITHM);
             md.update(data, offset, len);
             return md.digest();
 
         } catch (NoSuchAlgorithmException e) {
-            throw new ProviderException("Message digest Algorithm ("+md_alg+
-                                        ") missing ("+e.getMessage()+")");
+            throw new ProviderException("Message digest Algorithm ("+
+                        MD_ALGORITHM + ") missing ("+e.getMessage()+")");
         }
     }
 
@@ -252,13 +256,12 @@
      * data (as a byte array)
      * The digest uses the algorithm specified in 
      * crypto.message-digest.algorithm,
-     * and if not defined, defaults to the md_alg algorithm.
+     * and if not defined, defaults to the MD_ALGORITHM algorithm.
      *
      * @param data the data to be digested
      * @return the message digest (as a byte array)
      */
-    public static byte[] digest(byte[] data)
-    {
+    public static byte[] digest(byte[] data) {
         return digest(data, 0, data.length);
     }
 
@@ -277,7 +280,7 @@
      * @param len the length of the data with the data array
      * @return the encrypted data
      */
-    public static byte[] encrypt(Key key, byte[] data, int offset, int len)
+    private static byte[] encrypt(Key key, byte[] data, int offset, int len)
     {
         logDebug("encrypt() called");
         try {
@@ -287,7 +290,7 @@
             gzos.finish();
             byte[] zipped = baos.toByteArray();
 
-            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS#5",
+            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORM,
                                                "CryptixCrypto");
 
             // XXX: IV of all zeroes is a minor security problem
@@ -320,8 +323,7 @@
      * @param data the data being encrypted (as a byte array)
      * @return the encrypted data
      */
-    public static byte[] encrypt(Key key, byte[] data)
-    {
+    public static byte[] encrypt(Key key, byte[] data) {
       return encrypt(key, data, 0, data.length);
     }
 
@@ -337,12 +339,12 @@
      * @return the decrypted data
      * @excep KeyException is thrown if the data could not be decrypted
      */
-    public static byte[] decrypt(Key key, byte[] data, int offset, int len)
+    private static byte[] decrypt(Key key, byte[] data, int offset, int len)
         throws KeyException
     {
         logDebug("decrypt() called");
         try {
-            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS#5",
+            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORM,
                                                "CryptixCrypto");
 
             // XXX: IV of all zeroes is a minor security problem
@@ -383,9 +385,7 @@
      * @param data the data being decrypted (as a byte array)
      * @return the decrypted data
      */
-    public static byte[] decrypt(Key key, byte[] data)
-        throws KeyException
-    {
+    public static byte[] decrypt(Key key, byte[] data) throws KeyException {
       return decrypt(key, data, 0, data.length);
     }
 
@@ -506,22 +506,6 @@
       return pk_encrypt(key, pk, data, 0, data.length);
     }
 
-   /**
-     * Encrypt the data and return the encrypted binary data.
-     * The internal symmetric key is randomly generated.
-     *
-     * @param pk the PublicKey with which to encrypt the symmetric key
-     * @param data the data to be encrypted (as a byte array)
-     * @return the encrypted data (as a byte array)
-     * @exception KeyException a problem has occurred with the public key, 
-     * such as it not being in the correct format.
-     */
-    public static byte[] pk_encrypt(PublicKey pk, byte[] data)
-        throws KeyException
-    {
-      return pk_encrypt(generateKey(), pk, data, 0, data.length);
-    }
-
 
    /**
      * Decrypt the key portion of a public key encrypted packet.
@@ -533,52 +517,55 @@
      * @return the decrypted Key from the data header
      * @exception KeyException a problem has occurred with the private key
      */
-    public static Key pk_decrypt_key(PrivateKey pk, byte[] data, int offset, int len)
+    private static Key pk_decrypt_key(PrivateKey pk, 
+                                     byte[] data, int offset, int len)
         throws KeyException
     {
-      try {
-        //
-        // Decrypt the key
-        //
-        java.security.Cipher rsa = 
-            java.security.Cipher.getInstance(pk_alg);
-        rsa.initDecrypt(pk);
+        pk = translateKey(pk);
+        try {
+            //
+            // Decrypt the key
+            //
+            java.security.Cipher rsa = java.security.Cipher.getInstance(pk_alg);
+            rsa.initDecrypt(pk);
 
-        int pktlen = rsa.getCiphertextBlockSize() + 1;
+            int pktlen = rsa.getCiphertextBlockSize() + 1;
         
-        System.err.println("pktlen: " +pktlen+", data.length: "+data.length);
+            System.err.println("pktlen: "+pktlen+", data.length: "+data.length);
         
-        byte[] rsa_pkt = rsa.crypt(data, offset, pktlen);
-        len -= pktlen;
-        offset += pktlen;
+            byte[] rsa_pkt = rsa.crypt(data, offset, pktlen);
+            len -= pktlen;
+            offset += pktlen;
         
-        //
-        // Unpack the PKCS#1 packet
-        //
-        if (rsa_pkt[0] != 0)
-          throw new KeyException("Bad start of PKCS1 packet in decrypted data");
-        if (rsa_pkt[1] != 2)
-          throw new KeyException("Bad block type in decrypted data");
-
-
-        // Data starts after first zero octet
-        int pad_start = 2;
-        while(pad_start < rsa_pkt.length && rsa_pkt[pad_start++] != 0)
-          ;
-        if (pad_start == rsa_pkt.length)
-          throw new KeyException("Bad PKCS#1 packet in decrypted data");
-
-        byte[] key = new byte[rsa_pkt.length - pad_start];
-        if (key.length != cipher_keylen)
-          throw new KeyException("Unexpected size of PKCS#1 data field");
-
-        System.arraycopy(rsa_pkt, pad_start, key, 0, key.length);
-        return new RawSecretKey(cipher_alg, key);
-
-      } catch (NoSuchAlgorithmException e) {
-        throw new ProviderException(
-            pk_alg+" Algorithm not found ("+e.getMessage()+")");
-      }
+            //
+            // Unpack the PKCS#1 packet
+            //
+            if (rsa_pkt[0] != 0)
+                throw new KeyException(
+                    "Bad start of PKCS1 packet in decrypted data");
+
+            if (rsa_pkt[1] != 2)
+                throw new KeyException("Bad block type in decrypted data");
+
+            // Data starts after first zero octet
+            int pad_start = 2;
+            while(pad_start < rsa_pkt.length && rsa_pkt[pad_start++] != 0)
+                ;
+
+            if (pad_start == rsa_pkt.length)
+                throw new KeyException("Bad PKCS#1 packet in decrypted data");
+
+            byte[] key = new byte[rsa_pkt.length - pad_start];
+            if (key.length != cipher_keylen)
+                throw new KeyException("Unexpected size of PKCS#1 data field");
+
+            System.arraycopy(rsa_pkt, pad_start, key, 0, key.length);
+            return new RawSecretKey(CIPHER_ALGORITHM, key);
+
+        } catch (NoSuchAlgorithmException e) {
+            throw new ProviderException(
+                pk_alg+" Algorithm not found ("+e.getMessage()+")");
+        }
     }
 
    /**
@@ -595,25 +582,25 @@
      * @return the decrypted Key from the data header
      * @exception KeyException a problem has occurred with the private key
      */
-    public static byte[] pk_decrypt_data(PrivateKey pk, Key key, 
+    private static byte[] pk_decrypt_data(PrivateKey pk, Key key, 
                                          byte[] data, int offset, int len)
         throws KeyException
     {
-      try {
-        // Only using cipher to get packet length ...
-        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);
-      } catch (NoSuchAlgorithmException e) {
-        throw new ProviderException(
-            pk_alg+" Algorithm not found ("+e.getMessage()+")");
-      }
+        pk = translateKey(pk);
+        try {
+            // Only using cipher to get packet length ...
+            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);
+        } catch (NoSuchAlgorithmException e) {
+            throw new ProviderException(
+                pk_alg+" Algorithm not found ("+e.getMessage()+")");
+        }
     }
 
 
-   /**
+    /**
      * Decrypt data, and return the original plaintext
      *
      * @param pk a PrivateKey with which to decrypt the data
@@ -624,12 +611,12 @@
      * @exception KeyException a problem has occurred with the private key, 
      *            such as the password being incorrect.
      */
-    public static byte[] pk_decrypt(PrivateKey pk, 
+    /*package*/ static byte[] pk_decrypt(PrivateKey pk, 
                                     byte[] data, int offset, int len)
         throws KeyException
     {
-      Key key = pk_decrypt_key(pk, data, offset, len);
-      return pk_decrypt_data(pk, key, data, offset, len);
+        Key key = pk_decrypt_key(pk, data, offset, len);
+        return pk_decrypt_data(pk, key, data, offset, len);
     }
 
 
@@ -641,10 +628,10 @@
      * @return the decrypted Key from the data header
      * @exception KeyException a problem has occurred with the private key
      */
-    public static Key pk_decrypt_key(PrivateKey pk, byte[] data)
+    /*package*/ static Key pk_decrypt_key(PrivateKey pk, byte[] data)
         throws KeyException
     {
-      return pk_decrypt_key(pk, data, 0, data.length);
+        return pk_decrypt_key(pk, data, 0, data.length);
     }
 
    /**
@@ -658,35 +645,20 @@
      * @param data the data to be decrypted (as a byte array)
      * @return the decrypted Key from the data header
      * @exception KeyException a problem has occurred with the private key
-     */
-    public static byte[] pk_decrypt_data(PrivateKey pk, Key key, byte[] data)
-        throws KeyException
-    {
-      return pk_decrypt_data(pk, key, data, 0, data.length);
-    }
-
-   /**
-     * Decrypt data, and return the original plaintext
-     *
-     * @param pk a PrivateKey with which to decrypt the data
-     * @param data the data to be decrypted (as a byte array)
-     * @return the decrypted data (as a byte array)
-     * @exception KeyException a problem has occurred with the private key, 
-     *            such as the password being incorrect.
      */
-    public static byte[] pk_decrypt(PrivateKey pk, byte[] data)
+    /*package*/ static byte[] pk_decrypt_data(PrivateKey pk, 
+                                              Key key, byte[] data)
         throws KeyException
     {
-      return pk_decrypt(pk, data, 0, data.length);
+        return pk_decrypt_data(pk, key, data, 0, data.length);
     }
 
 
-
 ////////////////////////////////////////////////////////////////////////
 // Convenience methods for signing data and verifying the signatures
 ////////////////////////////////////////////////////////////////////////
 
-   /**
+    /**
      * Sign the data and return the binary X509 signature
      *
      * @param key a PrivateKey with which to sign the data
@@ -695,31 +667,24 @@
      * @exception KeyException a problem has occurred with the private key, 
      * such as the password being incorrect.
      */
-    public static byte[] sign(PrivateKey key, byte[] data)
-        throws KeyException
-    {
-      java.security.Signature sig;
-      try {
-        sig = java.security.Signature.getInstance(sig_alg); 
-      } catch (NoSuchAlgorithmException e) {
-        throw new ProviderException(
-            pk_alg+" Algorithm not found ("+e.getMessage()+")");
-      }
-
-      // Initialise the object with the private key
-      sig.initSign(key);
-
-      // Update and sign the data
-      try {
-                sig.update(data);
-                return encodeSignature(sig.sign());
-      } catch (SignatureException e) {
-        throw new InternalError("sign() failed ("+e.getMessage()+")");
-      }
+    public static byte[] sign(PrivateKey key, byte[] data) throws KeyException {
+        try {
+            Signature sig = Signature.getInstance(sig_alg); 
+            sig.initSign(key);
+            sig.update(data);
+            return encodeSignature(sig.sign());
+
+        } catch (NoSuchAlgorithmException e) {
+            throw new ProviderException(
+                pk_alg+" Algorithm not found ("+e.getMessage()+")");
+
+        } catch (SignatureException e) {
+            throw new InternalError("sign() failed ("+e.getMessage()+")");
+        }
     }
 
 
-   /**
+    /**
      * Determine whether the signature on the data is valid
      *
      * @param key a PublicKey with which to verify the signature
@@ -734,31 +699,21 @@
     public static boolean verify(PublicKey key, byte[] sigX509, byte[] data)
         throws KeyException
     {
-        java.security.Signature sig;
-        try
-        {
-            sig = java.security.Signature.getInstance(sig_alg); 
-        }
-        catch (NoSuchAlgorithmException e)
-        {
-            throw new ProviderException(pk_alg+" Algorithm not found ("+
-                                        e.getMessage()+")");
-        }
-
-        // Initialise the object with the public key
-        sig.initVerify(key);
+        try {
+            Signature sig = Signature.getInstance(sig_alg); 
+            sig.initVerify(key);
 
-        // Update and verify the data
-        // (remember to convert the X.509 sig to a standard one)
-        try
-        {
+            // Update and verify the data
+            // (remember to convert the X.509 sig to a standard one)
             sig.update(data);
             return sig.verify(decodeSignature(sigX509));
-        }
-        catch (SignatureException e)
-        {
+
+        } catch (NoSuchAlgorithmException e) {
+            throw new ProviderException(pk_alg+" Algorithm not found ("+
+                                        e.getMessage()+")");
+        } catch (SignatureException e) {
             e.printStackTrace();
-                return false;  // Assume that the signature was invalid
+            return false;  // Assume that the signature was invalid
         }
     }
 
@@ -770,11 +725,10 @@
     /**
      * Extract the key data (the bitstring) from the X509Key.
      */
-    private static byte[] keyData(PublicKey key)
-        throws InvalidKeyException
-    {
-        System.out.println("Fiets!");
+    private static byte[] keyData(PublicKey key) throws InvalidKeyException {
 
+        logDebug("keyData() called");
+
         /*
          * The X509Key is defined as:
          *
@@ -810,9 +764,8 @@
     * @exception InvalidKeyException the X509Key is invalid 
     *            (i.e. incorrectly formatted)
     */
-    public static byte[] fingerprint(PublicKey key)
-        throws InvalidKeyException
-    {
+    public static byte[] fingerprint(PublicKey key) throws InvalidKeyException {
+        key = translateKey(key);
         return digest(key.getEncoded());
     }
 
@@ -833,7 +786,7 @@
     public static byte[] decodeSignature(byte[] data)
         throws SignatureException
     {
-        System.out.println("Automobiel!");
+        
         /*
          * An X509 signature is defined as:
          *
@@ -942,8 +895,9 @@
      * @param key The encoded data containing the public key
      * @return the encoded key (as a byte array)
      */
-    public static byte[] encodePublicKey(PublicKey key)
-    {
+    public static byte[] encodePublicKey(PublicKey key) {
+        key = translateKey(key);
+
         /*
          * An RSA public key is defined as:
          *       
@@ -1050,6 +1004,7 @@
      */
     public static byte[] encodePrivateKey(PrivateKey key)
     {
+        key = translateKey(key);
         // An RSA private key is defined as:
         //
         // SEQUENCE {
@@ -1106,21 +1061,47 @@
         }
     }
 
+    private static PrivateKey translateKey(PrivateKey key) {
+        if( key.getFormat().equals("Cryptix") ) {
+            RSAPrivateCrtKey rsapk = (RSAPrivateCrtKey)key;
+            return new RawRSAPrivateKey(
+                rsapk.getPrivateExponent(),
+                rsapk.getPrimeP(),
+                rsapk.getPrimeQ(),
+                rsapk.getCrtCoefficient() );
+        }
 
+        return key;
+    }
+
+
+    private static PublicKey translateKey(PublicKey key) {
+        return toCryptixKey(key);
+    }
+
+
     /**
      * 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) {
+    public 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.
-         */
+         1G*/
         if( pk.getFormat().equals("RAW") )
             return pk;
+
+        if( pk.getFormat().equals("Cryptix") ) {
+            RSAPublicKey rsapk = (RSAPublicKey)pk;
+            BigInteger n = rsapk.getModulus();
+            BigInteger e = rsapk.getPublicExponent();
+            return new RawRSAPublicKey(n, e);   
+        }
+
 
         try {
             AsnInputStream is = new AsnInputStream(pk.getEncoded());