harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mloe...@apache.org
Subject svn commit: r430356 - in /incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool: ArgumentsParser.java KeyCertGenerator.java KeyStoreConverter.java Main.java
Date Thu, 10 Aug 2006 11:02:27 GMT
Author: mloenko
Date: Thu Aug 10 04:02:27 2006
New Revision: 430356

URL: http://svn.apache.org/viewvc?rev=430356&view=rev
Log:
applied patch for HARMONY-1132
[tools] Keytool - added key and certificate generation, keystore format converting

Added:
    incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyCertGenerator.java
    incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyStoreConverter.java
Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/ArgumentsParser.java
    incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/Main.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/ArgumentsParser.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/ArgumentsParser.java?rev=430356&r1=430355&r2=430356&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/ArgumentsParser.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/ArgumentsParser.java
Thu Aug 10 04:02:27 2006
@@ -545,6 +545,33 @@
         }
         
         switch (command) {
+            case GENKEY:
+                // if the distinguished name is not specified, get the
+                // necessary data
+                if (param.getDName() == null && !param.isSecretKey()) {
+                    param.setDName(getDistinguishedName());
+                }
+                // if the key password has not been entered (and can equal store
+                // password)
+                if (param.getKeyPass() == null) {
+                    param.setKeyPass(getNewPassword(null, alias, param
+                            .getStorePass()));
+                }
+                
+                String issuerAlias = param.getIssuerAlias(); 
+                // if the newly generated certificate should be signed with 
+                // another certificate chain from the keystore. 
+                if (issuerAlias != null && !param.isSecretKey()) {
+                    // Ñheck if the issuer password was entered. If not, try storepass.
+                    // If it's not ok, prompt the user.
+                    if (param.getIssuerPass() == null) {
+                        param.setIssuerPass(tryStorePassAsKeyPass(keyStore, issuerAlias,
+                                param.getStorePass()));
+                    }
+                }
+                
+                break;
+
             case KEYCLONE:
                 // prompt for a destination alias, if one is not specified
                 if (param.getDestAlias() == null) {
@@ -633,6 +660,100 @@
                 break;
         }// switch (param.getCommand())
 
+    }
+
+    /**
+     * The method prompts user to enter data to initialize an X.500
+     * Distinguished Name to create a new certificate. It gets the data asks if
+     * it is correct, and if it is returns the String representing the
+     * distinguished name, if the data entered is not correct prompts to enter
+     * it again.
+     * 
+     * @return - String representing the distinguished names
+     */
+    private static String getDistinguishedName() throws IOException,
+            KeytoolException {
+        // X.500 principal: CN, OU, O, L, ST, C;
+        String[] dnFields = { "CN=", ", OU=", ", O=", ", L=", ", ST=", ", C=" };
+        // the flag is set to true, when the user confirms that
+        // the data he (or she) entered is correct.
+        boolean isCorrect = false;
+        // X.500 Dinsinguished Name. It will look like:
+        // "CN=user_name, OU=org_unit, O=organization, L=city, ST=state,
+        // C=com"
+        StringBuffer dname = new StringBuffer(256);
+        // the flag is set to true when there are spaces and/or commas in
+        // the fields of the distinguished name
+        boolean needQuotes = false;
+
+        // data that user enters is saved here
+        StringBuffer[] dnFieldsData = new StringBuffer[] {
+                new StringBuffer("Unknown"), new StringBuffer("Unknown"),
+                new StringBuffer("Unknown"), new StringBuffer("Unknown"),
+                new StringBuffer("Unknown"), new StringBuffer("Unknown") };
+
+        // prompts to show to user when asking to enter some data
+        String[] prompts = { "Enter your first and last name: ",
+                "Enter the name of your organizational unit: ",
+                "Enter the name of your organization: ",
+                "Enter the name of your city or locality: ",
+                "Enter the name of your state or province: ",
+                "Enter the two-letter country code for the unit: ",
+                "Is the information you entered correct? [no]: " };
+
+        // do it until user confirms that the data he entered is true.
+        while (!isCorrect) {
+            // clear dname if it is not empty
+            if (dname.length() > 0) {
+                dname.delete(0, dname.length());
+            }
+            for (int i = 0; i < dnFieldsData.length; i++) {
+                // ask the user to enter info
+                System.out.println(prompts[i]);
+                // print the current value of the field
+                System.out.print("[" + dnFieldsData[i] + "]: ");
+                dname.append(dnFields[i]);
+                charsRead = in.read(readData);
+                // if something was entered put the new value to
+                // dnFieldsData
+                // else don't change what was entered before.
+                if (charsRead > newLineLength) {
+                    // check whether quotes are needed.
+                    needQuotes = false;
+                    for (int j = 0; j < charsRead - newLineLength; j++) {
+                        if (readData[j] == ',' || readData[j] == ' ') {
+                            needQuotes = true;
+                            break;
+                        }
+                    }
+                    // if quotes are not needed
+                    if (!needQuotes) {
+                        // copy the read data into the StringBuffer.
+                        // don't need the '\r' and \n' in the end
+                        dnFieldsData[i].insert(0, readData, 0, charsRead
+                                - newLineLength);
+                        dnFieldsData[i].delete(charsRead - newLineLength,
+                                dnFieldsData[i].length());
+                    } else {// if quotes are needed, add them to the begin
+                        // and to the end
+                        dnFieldsData[i].insert(0, '\"');
+                        dnFieldsData[i].insert(1, readData, 0, charsRead
+                                - newLineLength);
+                        dnFieldsData[i].insert(charsRead - 1, '\"');
+                        dnFieldsData[i].delete(charsRead, dnFieldsData[i]
+                                .length());
+                    }
+                }
+                dname.append(dnFieldsData[i]);
+            }
+            // print the distinguished name with the fields filled
+            System.out.println(dname);
+            // confirm, if the user enters 'y' or "yes"
+            // any other input results in asking the questions again
+            isCorrect = getConfirmation(prompts[prompts.length - 1], true);
+        }
+        // save the data when got the confirmation from the user
+        return new String(dname);
     }
 
     /**

Added: incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyCertGenerator.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyCertGenerator.java?rev=430356&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyCertGenerator.java
(added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyCertGenerator.java
Thu Aug 10 04:02:27 2006
@@ -0,0 +1,592 @@
+/*
+ * Copyright 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.harmony.tools.keytool;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Random;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.apache.harmony.crypto.utils.AlgNameMapper;
+import org.apache.harmony.security.provider.cert.X509CertImpl;
+import org.apache.harmony.security.x501.Name;
+import org.apache.harmony.security.x509.AlgorithmIdentifier;
+import org.apache.harmony.security.x509.Extension;
+import org.apache.harmony.security.x509.Extensions;
+import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
+import org.apache.harmony.security.x509.TBSCertificate;
+import org.apache.harmony.security.x509.Validity;
+
+/**
+ * Class for generating keys and key pairs, wrapping them into self-signed X.509
+ * certificates.
+ */
+public class KeyCertGenerator {
+    
+    /**
+     * Generates a key pair or a secret key. Key pair is composed of a private
+     * and a public key. Method wraps the public key into a self-signed X.509
+     * (v1, v2, v3) certificate and puts the certificate into a single-element
+     * certificate chain or signs the certificate with private key from another
+     * key entry and adds its chain to the newly generated certificate . After
+     * that the method adds to the keystore a new entry containing the generated
+     * private key and the chain. If a secret key is generated it is put into a
+     * secret key entry, with null certificate chain.
+     * 
+     * @throws NoSuchAlgorithmException
+     * @throws KeyStoreException
+     * @throws KeytoolException
+     * @throws IOException
+     * @throws SignatureException
+     * @throws NoSuchProviderException
+     * @throws InvalidKeyException
+     * @throws UnrecoverableKeyException
+     * @throws CertificateException
+     */
+    static void genKey(KeytoolParameters param)
+            throws NoSuchAlgorithmException, KeyStoreException,
+            KeytoolException, InvalidKeyException, NoSuchProviderException,
+            SignatureException, IOException, UnrecoverableKeyException,
+            CertificateException {
+
+        if (param.isSecretKey()) {
+            generateSecretKey(param);
+        } else {
+            generatePrivateKey(param);
+        }
+    }
+
+    // Generates a key pair composed of a private and a public key, wraps the
+    // public key into a self-signed X.509 (v1, v2, v3) certificate, puts the
+    // certificate into a single-element certificate chain and adds to the
+    // keystore a new entry containing the private key and the chain.
+    private static void generatePrivateKey(KeytoolParameters param)
+            throws NoSuchAlgorithmException, KeyStoreException,
+            NoSuchProviderException, InvalidKeyException, SignatureException,
+            IOException, KeytoolException, UnrecoverableKeyException,
+            CertificateException {
+
+        KeyStore keyStore = param.getKeyStore();
+
+        PrivateKey issuerPrivateKey = null;
+        Certificate[] issuerCertChain = null;
+        String issuerDN = null;
+        // if the generated certificate shouldn't be self-signed
+        // but should be signed with a chain.
+        boolean selfSigned = (param.getIssuerAlias() == null);
+        if (!selfSigned) {
+            String issuerAlias = param.getIssuerAlias();
+            if (!keyStore.containsAlias(issuerAlias)) {
+                throw new KeytoolException("Certificate issuer alias <"
+                        + issuerAlias + "> does not exist.");
+            }
+
+            if (!keyStore.entryInstanceOf(issuerAlias,
+                    KeyStore.PrivateKeyEntry.class)) {
+                throw new KeytoolException("Issuer alias <" + issuerAlias
+                        + "> is not a private key entry. ");
+            }
+            issuerCertChain = keyStore.getCertificateChain(issuerAlias);
+            issuerPrivateKey = (PrivateKey) keyStore.getKey(issuerAlias, param
+                    .getIssuerPass());
+            issuerDN = ((X509Certificate) issuerCertChain[0])
+                    .getSubjectX500Principal().getName();
+        }
+
+        KeyPairGenerator kpg = null;
+        String keyAlg = param.getKeyAlg();
+        // key algorithm is DSA by default
+        if (keyAlg == null) {
+            keyAlg = "DSA";
+        }
+
+        String sigAlgName = null;
+
+        // if signature algorithm is not set, use a default
+        if (param.getSigAlg() != null) {
+            sigAlgName = param.getSigAlg();
+        } else if (selfSigned) {
+            if (keyAlg.equalsIgnoreCase("DSA")) {
+                sigAlgName = "SHA1withDSA";
+            } else if (keyAlg.equalsIgnoreCase("RSA")) {
+                sigAlgName = "MD5withRSA";
+            }
+        } else {
+            String issuerKeyAlg = issuerPrivateKey.getAlgorithm();
+            if (issuerKeyAlg.equalsIgnoreCase("DSA")) {
+                sigAlgName = "SHA1withDSA";
+            } else if (issuerKeyAlg.equalsIgnoreCase("RSA")) {
+                sigAlgName = "MD5withRSA";
+            } else {
+                // FIXME: can a kind of search be done?
+                throw new KeytoolException(
+                        "Cannot find signature algorithm for issuer's key algorithm "
+                                + issuerKeyAlg);
+            }
+        }
+        // set the certificate validity period
+        // 90 days by default
+        long validity = (param.getValidity() != 0) ? param.getValidity() : 90;
+
+        // set the X.509 version to use with the certificate
+        int version = (param.getX509version() != 0) ?
+        // TBSCertificate needs 0, 1 or 2 as version in constructor (not 1,2,3);
+                // X.509 v.3 certificates by default
+                param.getX509version() - 1 : 2;
+
+        // set certificate serial number
+        BigInteger serialNr;
+        if (param.getCertSerialNr() != 0) {
+            serialNr = BigInteger.valueOf(param.getCertSerialNr());
+        } else {
+            int randomInt = new Random().nextInt();
+            if (randomInt < 0) {
+                randomInt = -randomInt;
+            }
+            serialNr = BigInteger.valueOf(randomInt);
+        }
+
+        int keySize = param.getKeySize();
+        if (param.isVerbose()) {
+            StringBuffer strBuf = new StringBuffer("Genarating a " + keyAlg
+                    + " key pair, key length " + keySize + " bit \nand a ");
+            if (selfSigned) {
+                strBuf.append("self-signed ");
+            }
+            strBuf.append("certificate (signature algorithm is " + sigAlgName
+                    + ")\n for " + param.getDName());
+            System.out.println(strBuf);
+        }
+
+        // generate a pair of keys
+        String provider = param.getProvider();
+        String keyProvider = (param.getKeyProvider() != null) ? param
+                .getKeyProvider() : provider;
+        try {
+            if (keyProvider == null) {
+                kpg = KeyPairGenerator.getInstance(keyAlg);
+            } else {
+                kpg = KeyPairGenerator.getInstance(keyAlg, keyProvider);
+            }
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("The algorithm " + keyAlg
+                    + " is not available in current environment.");
+        } catch (NoSuchProviderException e) {
+            throw (NoSuchProviderException) new NoSuchProviderException(
+                    "The provider " + keyProvider
+                            + " is not found in the environment.").initCause(e);
+        }
+        // initialize the KeyPairGenerator with the key size
+        kpg.initialize(keySize);
+
+        KeyPair keyPair = kpg.genKeyPair();
+        PrivateKey privateKey = keyPair.getPrivate();
+
+        String subjectDN = param.getDName();
+        String sigProvider = (param.getSigProvider() != null) ? param
+                .getSigProvider() : provider;
+
+        if (selfSigned) {
+            // generate the certificate
+            X509CertImpl x509cert = genX509CertImpl(sigAlgName, version,
+                    serialNr, subjectDN, subjectDN, validity, keyPair
+                            .getPublic(), privateKey, sigProvider,
+                    param.isCA());
+
+            // put the key pair with the newly created cert into the keystore
+            keyStore.setKeyEntry(param.getAlias(), privateKey, param
+                    .getKeyPass(), new X509Certificate[] { x509cert });
+
+        } else {
+            // generate the certificate
+            X509CertImpl x509cert = genX509CertImpl(sigAlgName, version,
+                    serialNr, subjectDN, issuerDN, validity, keyPair
+                            .getPublic(), issuerPrivateKey,
+                    sigProvider, param.isCA());
+
+            // construct the certificate chain
+            int issuerChainLength = issuerCertChain.length;
+            X509Certificate[] certChain = new X509Certificate[issuerChainLength + 1];
+            certChain[0] = x509cert;
+            System.arraycopy(issuerCertChain, 0, certChain, 1,
+                    issuerChainLength);
+
+            // put the key pair with the newly created cert into the keystore
+            keyStore.setKeyEntry(param.getAlias(), privateKey, param
+                    .getKeyPass(), certChain);
+
+        }
+
+        param.setNeedSaveKS(true);
+    }
+
+    /**
+     * Generates an X.509 (v1, v2, v3) self-signed certificate using a key pair
+     * associated with alias defined in param. If X.500 Distinguished Name is
+     * supplied in param it is used as both subject and issuer of the
+     * certificate. Otherwise the distinguished name associated with alias is
+     * used. Signature algorithm, validity period and certificate serial number
+     * are taken from param if defined there or from the keystore entry
+     * identified by alias.
+     * 
+     * @throws NoSuchAlgorithmException
+     * @throws KeyStoreException
+     * @throws UnrecoverableKeyException
+     * @throws IOException
+     * @throws NoSuchProviderException
+     * @throws SignatureException
+     * @throws InvalidKeyException
+     * @throws KeytoolException
+     * @throws CertificateException 
+     */
+    static void selfCert(KeytoolParameters param)
+            throws NoSuchAlgorithmException, KeyStoreException,
+            UnrecoverableKeyException, InvalidKeyException, SignatureException,
+            NoSuchProviderException, IOException, KeytoolException,
+            CertificateException {
+
+        String alias = param.getAlias();
+        KeyStore keyStore = param.getKeyStore();
+
+        if (!keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
+            throw new KeytoolException("Failed to generate a certificate. "
+                    + "Entry <" + alias + "> is not a private key entry");
+        }
+
+        // get the keys and the certificate from the keystore
+        PrivateKey privateKey;
+        try {
+            privateKey = (PrivateKey) keyStore
+                    .getKey(alias, param.getKeyPass());
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException(
+                    "Cannot find the algorithm to recover the key. ", e);
+        }
+
+        // get the cersificate currently associated with the alias
+        X509Certificate existing = (X509Certificate) keyStore
+                .getCertificate(alias);
+
+        // setting certificate attributes
+        // signature algorithm name
+        String sigAlgName = (param.getSigAlg() != null) ? param.getSigAlg()
+                : existing.getSigAlgName();
+
+        // X.500 distinguished name
+        String distinguishedName = (param.getDName() != null) ? param
+                .getDName() : existing.getSubjectDN().getName();
+
+        // validity period. It is 90 days by default
+        long validity = (param.getValidity() != 0) ? param.getValidity() : 90;
+
+        // set the X.509 version to use with the certificate
+        int version = (param.getX509version() != 0) ?
+        // TBSCertificate needs 0, 1 or 2 as version in constructor (not 1,2,3);
+                param.getX509version() - 1 : 2; // X.509 v.3 certificates by default
+        
+
+        // set certificate serial number
+        int randomInt = new Random().nextInt();
+        if (randomInt < 0) {
+            randomInt = -randomInt;
+        }
+        BigInteger serialNr = (param.getCertSerialNr() != 0) ? BigInteger
+                .valueOf(param.getCertSerialNr()) : BigInteger
+                .valueOf(randomInt);
+
+        // generate a new certificate
+        String sigProvider = (param.getSigProvider() != null) ? param
+                .getSigProvider() : param.getProvider();
+        X509CertImpl x509cert = genX509CertImpl(sigAlgName, version, serialNr,
+                distinguishedName, distinguishedName, validity, existing
+                        .getPublicKey(), privateKey, sigProvider, param.isCA());
+
+        if (param.isVerbose()) {
+            System.out.println("New self-signed certificate: ");
+            System.out.println("Version: v" + x509cert.getVersion());
+            System.out.println("Owner: " + x509cert.getSubjectX500Principal());
+            System.out.println("Issuer: " + x509cert.getIssuerX500Principal());
+            System.out.println("Public key: " + x509cert.getPublicKey());
+            System.out
+                    .println("Signature algorithm: OID."
+                            + x509cert.getSigAlgOID() + ", "
+                            + x509cert.getSigAlgName());
+            System.out
+                    .println("Serial number: "
+                            // String.format("%x", x509cert.getSerialNumber()));
+                            // TODO: print with String.format(..) when the
+                            // method is
+                            // implemented, and remove Integer.toHexString(..).
+                            + Integer.toHexString(x509cert.getSerialNumber()
+                                    .intValue()));
+
+            System.out.println("Validity: \n    From: "
+                    + x509cert.getNotBefore() + "\n      To: "
+                    + x509cert.getNotAfter());
+        }
+
+        // put the new certificate into the entry, associated with the alias
+        keyStore.setKeyEntry(alias, privateKey, param.getKeyPass(),
+                new X509Certificate[] { x509cert });
+        param.setNeedSaveKS(true);
+    }
+
+    // Generates an X.509 certificate (instance of X509CertImpl class) based
+    // on given paramaters.
+    // 
+    // @param sigAlgName
+    // the name of the signature algorithm to use
+    // @param version
+    // version of X.509 protocol to use. May be one of 0 (v1), 1 (v2)
+    // or 2 (v3)
+    // @param serialNr
+    // certificate serial number
+    // @param strSubjectDN
+    // X.500 Distinguished Name to use as subject
+    // @param strIssuerDN
+    // X.500 Distinguished Name to use as issuer
+    // @param validity
+    // certificate validity period in days after the current moment
+    // @param publicKey
+    // public key to wrap in certificate
+    // @param privateKey
+    // private key to sign the certificate
+    // @param provider
+    // provider name to use when generating a signature
+    // @return X.509 certificate
+    private static X509CertImpl genX509CertImpl(String sigAlgName, int version,
+            BigInteger serialNr, String strSubjectDN, String strIssuerDN,
+            long validity, PublicKey publicKey, PrivateKey privateKey,
+            String provider, boolean isCA) throws InvalidKeyException, SignatureException,
+            NoSuchAlgorithmException, IOException, NoSuchProviderException {
+
+        String[] sigAlgNameAndOID = getAlgNameAndOID(sigAlgName);
+        if (sigAlgNameAndOID[0] == null || sigAlgNameAndOID[1] == null) {
+            throw new NoSuchAlgorithmException("The algorithm " + sigAlgName
+                    + " is not found in the environment.");
+        }
+        sigAlgName = sigAlgNameAndOID[0];
+        String sigAlgOID = sigAlgNameAndOID[1];
+
+        AlgorithmIdentifier algId = new AlgorithmIdentifier(sigAlgOID);
+
+        // generate a distinguished name using the string
+        Name subjectDName = null;
+        Name issuerDName = null;
+        try {
+            subjectDName = new Name(strSubjectDN);
+
+            if (strSubjectDN.equals(strIssuerDN)) {
+                issuerDName = subjectDName;
+            } else {
+                issuerDName = new Name(strIssuerDN);
+            }
+        } catch (IOException e) {
+            throw (IOException) new IOException(
+                    "Failed to generate a distinguished name. ").initCause(e);
+        }
+
+        // generate a SubjectPublicKeyInfo
+        SubjectPublicKeyInfo subjectPublicKeyInfo = null;
+        try {
+            subjectPublicKeyInfo = (SubjectPublicKeyInfo) SubjectPublicKeyInfo.ASN1
+                    .decode(publicKey.getEncoded());
+        } catch (IOException e) {
+            throw (IOException) new IOException(
+                    "Failed to decode SubjectPublicKeyInfo. ").initCause(e);
+        }
+        
+        Extensions extensions = null;
+        
+        if (version == 1 || version == 2) {
+            // generate extensions
+            ArrayList<Object> basicConstraints = new ArrayList<Object>(2);
+            basicConstraints.add(new Boolean(isCA));
+            basicConstraints.add(BigInteger.valueOf(Integer.MAX_VALUE));
+            extensions = new Extensions(Collections
+                    .singletonList(new Extension.BasicConstraints(
+                            basicConstraints, false)));
+        }       
+        // generate the TBSCertificate to put it into the X.509 cert
+        TBSCertificate tbsCertificate = new TBSCertificate(
+        // version
+                version,
+                // serial number
+                serialNr,
+                // signature algorithm identifier
+                algId,
+                // issuer
+                issuerDName,
+                // validity
+                new Validity(new Date(System.currentTimeMillis()), // notBefore
+                        new Date(System.currentTimeMillis()
+                        // 86400000 milliseconds in a day
+                                + validity * 86400000)), // notAfter
+                // subject
+                subjectDName,
+                // subjectPublicKeyInfo
+                subjectPublicKeyInfo,
+                // issuerUniqueID
+                null,
+                // subjectUniqueID
+                null, 
+                // basic constraints
+                extensions);
+        // get the TBSCertificate encoding
+        byte[] tbsCertEncoding = tbsCertificate.getEncoded();
+
+        // generate the signature
+        Signature sig = null;
+        try {
+            sig = (provider == null) ? Signature.getInstance(sigAlgName)
+                    : Signature.getInstance(sigAlgName, provider);
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("The algorithm " + sigAlgName
+                    + " is not found in the environment.", e);
+        } catch (NoSuchProviderException e) {
+            throw (NoSuchProviderException) new NoSuchProviderException(
+                    "The provider " + provider
+                            + " is not found in the environment.").initCause(e);
+        }
+
+        try {
+            sig.initSign(privateKey);
+        } catch (InvalidKeyException e) {
+            throw new InvalidKeyException(
+                    "The private key used to generate the signature is invalid.",
+                    e);
+        }
+
+        byte[] signatureValue = null;
+        try {
+            sig.update(tbsCertEncoding, 0, tbsCertEncoding.length);
+            signatureValue = sig.sign();
+        } catch (SignatureException e) {
+            throw new SignatureException("Failed to sign the certificate. ", e);
+        }
+
+        // actual X.509 certificate generation
+        org.apache.harmony.security.x509.Certificate cert;
+        cert = new org.apache.harmony.security.x509.Certificate(tbsCertificate,
+                algId, signatureValue);
+        return new X509CertImpl(cert);
+    }
+
+    // generates a secret key and puts it into a newly created secret key entry.
+    private static void generateSecretKey(KeytoolParameters param)
+            throws NoSuchAlgorithmException, NoSuchProviderException,
+            KeyStoreException, CertificateException, FileNotFoundException,
+            IOException, KeytoolException {
+
+        String keyAlg = param.getKeyAlg();
+        int keySize = param.getKeySize();
+
+        if (keyAlg == null) {
+            keyAlg = "DES";
+        } else {
+            keyAlg = getAlgNameAndOID(keyAlg)[0];
+        }
+        if (param.isVerbose()) {
+            System.out.println("Generating a new secret key: ");
+            System.out.println("Algorithm: " + keyAlg);
+            System.out.println("Key size: " + keySize);
+        }
+        KeyGenerator keyGen;
+        String keyProvider = (param.getKeyProvider() != null) ? param
+                .getKeyProvider() : param.getProvider();
+        try {
+
+            if (keyProvider == null) {
+                keyGen = KeyGenerator.getInstance(keyAlg);
+            } else {
+                keyGen = KeyGenerator.getInstance(keyAlg, keyProvider);
+            }
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("The algorithm " + keyAlg
+                    + " is not found in the environment.", e);
+        } catch (NoSuchProviderException e) {
+            throw (NoSuchProviderException) new NoSuchProviderException(
+                    "The provider " + keyProvider
+                            + " is not found in the environment.").initCause(e);
+        }
+
+        keyGen.init(keySize);
+        SecretKey key = keyGen.generateKey();
+
+        KeyStore keyStore = param.getKeyStore();
+
+        // keyStore.setKeyEntry(param.getAlias(), key, param.getKeyPass(),
+        // null);
+
+        keyStore.setEntry(param.getAlias(), new KeyStore.SecretKeyEntry(key),
+                new KeyStore.PasswordProtection(param.getKeyPass()));
+
+        param.setNeedSaveKS(true);
+    }
+
+    // Method gets algorithm name (it can be an algorithm alias, OID or standard
+    // algorithm name) and returns String array, which has standard name as the
+    // first element and OID as the second.
+    // If algName is OID and the mapping is not found in providers available,
+    // first element can be null.
+    // If algName is a standard format (not an OID) and the mapping is not found
+    // second element of the returned array can be null. If the algorithm name
+    // itself is not found algName is returned as the first element.
+    private static String[] getAlgNameAndOID(String algName)
+            throws NoSuchAlgorithmException {
+        String algOID = null;
+        String standardName = null;
+        if (AlgNameMapper.isOID(algName.toUpperCase())) {
+            // if algName is OID, remove the leading "OID." and
+            // copy it to algOID
+            algOID = AlgNameMapper.normalize(algName.toUpperCase());
+            // convert OID to a normal algorithm name.
+            standardName = AlgNameMapper.map2AlgName(algOID);
+        } else {
+            // if algName is not an OID, convert it into a standard name and
+            // get its OID and put to algOID
+            standardName = AlgNameMapper.getStandardName(algName);
+            if (standardName == null) {
+                return new String[] { algName, null };
+            }
+            algOID = AlgNameMapper.map2OID(standardName);
+        }
+        return new String[] { standardName, algOID };
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyStoreConverter.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyStoreConverter.java?rev=430356&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyStoreConverter.java
(added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/KeyStoreConverter.java
Thu Aug 10 04:02:27 2006
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.harmony.tools.keytool;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+
+/**
+ * Class to convert keystore to another format.
+ */
+public class KeyStoreConverter {
+    /**
+     * Converts keystore to another format.
+     * 
+     * @param param
+     * @throws KeyStoreException
+     * @throws FileNotFoundException
+     * @throws NoSuchAlgorithmException
+     * @throws CertificateException
+     * @throws NoSuchProviderException
+     * @throws IOException
+     * @throws KeytoolException
+     */
+    static void convertKeyStore(KeytoolParameters param)
+            throws KeyStoreException, FileNotFoundException,
+            NoSuchAlgorithmException, CertificateException,
+            NoSuchProviderException, IOException, KeytoolException {
+
+        // get the main keystore
+        KeyStore mainKS = param.getKeyStore();
+        String ksProvider = (param.getConvKsProvider() != null) ? param
+                .getConvKsProvider() : param.getProvider();
+        // creating a new keystore
+        KeyStore convertedKS = KeyStoreLoaderSaver.loadStore(null, param
+                .getConvertedKeyStoreType(), param.getConvertedKeyStorePass(),
+                ksProvider);
+
+        // get the aliases enumeration
+        Enumeration aliases = mainKS.aliases();
+        // counts converted entries
+        int convertedCnt = 0;
+
+        // if key entries should be converted just as certificate entries  
+        if (param.isConvertKeyEntries()) { 
+            // make a ProtectionParameter from main keystore password
+            KeyStore.PasswordProtection mainKSpass = 
+                new KeyStore.PasswordProtection(param.getStorePass());
+
+            // make a ProtectionParameter from password of keystore 
+            // to convert to
+            KeyStore.PasswordProtection convertedKSpass = 
+                new KeyStore.PasswordProtection(param.getConvertedKeyStorePass());
+
+            while (aliases.hasMoreElements()) {
+                String alias = (String) aliases.nextElement();
+                try {
+                    // if the entry is a certificate entry
+                    if (mainKS.isCertificateEntry(alias)) {
+                        convertedKS.setCertificateEntry(alias, mainKS
+                                .getCertificate(alias));
+                    } else {
+                        // try to get the entry using the keystore password
+                        KeyStore.Entry entry = mainKS.getEntry(alias,
+                                mainKSpass);
+                        convertedKS.setEntry(alias, entry, convertedKSpass);
+                    }
+
+                    // won't come here if exception is thrown
+                    ++convertedCnt;
+                } catch (Exception e) {
+                    // Catch exception here, because program should 
+                    // try to continue the work.
+                    System.out.println("Failed to convert the entry <" + alias
+                            + ">.");
+                    System.out.println("\tReason: " + e);
+                }
+            } // while (aliases.hasMoreElements())...
+        } else {
+            while (aliases.hasMoreElements()) {
+                String alias = (String) aliases.nextElement();
+                try {
+                    if (mainKS.isCertificateEntry(alias)) {
+                        convertedKS.setCertificateEntry(alias, mainKS
+                                .getCertificate(alias));
+                    }
+
+                    // won't come here if exception is thrown
+                    ++convertedCnt;
+                } catch (Exception e) {
+                    // Catch exception here, because program should 
+                    // try to continue the work.
+                    System.out.println("Failed to convert the entry <" + alias
+                            + ">.");
+                    System.out.println("Reason: " + e);
+                }
+            }
+        } //if (!param.isConvertKeyEnties()) ...
+        
+        if (param.isVerbose()){
+            System.out.println("Converted " + convertedCnt + " entries");
+        }
+            
+        // save the converted keystore
+        KeyStoreLoaderSaver.saveStore(convertedKS, param
+                .getConvertedKeyStorePath(), param.getConvertedKeyStorePass(),
+                param.isVerbose());
+    }
+}
+

Modified: incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/Main.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/Main.java?rev=430356&r1=430355&r2=430356&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/Main.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/keytool/Main.java
Thu Aug 10 04:02:27 2006
@@ -65,9 +65,21 @@
                 CSRGenerator.certReq(param);
                 break;
             case HELP:
-            	HelpPrinter.printHelp();
+                if (param.getHelpTopic() != null){
+                    HelpPrinter.topicHelp(param.getHelpTopic());
+                } else {
+                    HelpPrinter.printHelp();
+                }
+                break;
+            case GENKEY:
+                KeyCertGenerator.genKey(param);
+                break;
+            case SELFCERT:
+                KeyCertGenerator.selfCert(param);
+                break;
+            case CONVERT:
+                KeyStoreConverter.convertKeyStore(param);
                 break;
-            // TODO: calls for other options.    
         }
     }
 



Mime
View raw message