org.openuat.channel
Class X509CertificateGenerator

java.lang.Object
  extended by org.openuat.channel.X509CertificateGenerator

public class X509CertificateGenerator
extends java.lang.Object

This class uses the Bouncycastle lightweight API to generate X.509 certificates programmatically. It assumes a CA certificate and its private key to be available and can sign the new certificate with this CA. Some of the code for this class was taken from org.bouncycastle.x509.X509V3CertificateGenerator, but adapted to work with the lightweight API instead of JCE (which is usually not available on MIDP2.0).

Version:
1.0
Author:
Rene Mayrhofer

Field Summary
static java.lang.String CertificateExportFriendlyName
          This string is used as the friendly name for the certificate in the PKCS12 exported file.
static java.lang.String CertificateSignatureAlgorithm
          This method is used for signing the certificate.
static java.lang.String KeyExportFriendlyName
          This string is used as the friendly name for the private key in the PKCS12 exported file.
 
Constructor Summary
protected X509CertificateGenerator(boolean useBCAPI)
          Initializes the objects without an existing CA.
  X509CertificateGenerator(java.lang.String caFile, java.lang.String caPassword, java.lang.String caAlias, boolean useBCAPI)
          Initializes the object for creating certificates by loading the CA certificate and private key.
 
Method Summary
static boolean convertPKCS12toPEM(java.lang.String inFile, java.lang.String inPassword, java.lang.String outCertFile, java.lang.String outKeyFile, java.lang.String outCertChainFile, boolean useBCAPI)
          Converts from a PKCS12 encoded file to PEM encoded files readable by openssl (and subsequently e.g. openswan and racoon).
 boolean createCertificate(java.lang.String commonName, int validityDays, java.lang.String exportFile, java.lang.String exportPassword)
          This method should create something similar to: openssl req -new -outform PEM -newkey rsa:1024 -nodes -keyout /tmp/test.key -keyform PEM -out /tmp/test.pem -days 30 -config /etc/ssl/openssl.cnf openssl ca -policy policy_anything -out /tmp/test.crt -config /etc/ssl/openssl.cnf -infiles /tmp/test.pem openssl pkcs12 -export -in /tmp/test.crt -inkey /tmp/test.key -certfile demoCA/cacert.pem -out test.p12
protected  boolean createCertificate(java.lang.String commonName, int validityDays, java.lang.String exportFile, java.lang.String exportPassword, java.lang.String exportAlias)
          This method implements the public one, but offers an additional parameter which is only used when creating a new CA, namely the export alias to use.
static boolean createNewCa(java.lang.String commonName, int validityDays, java.lang.String caFile, java.lang.String caPassword, java.lang.String caAlias, boolean useBCAPI)
          Creates a new self-signed CA (certificate authority) for subsequently signing certificates.
 java.lang.String getCaDistinguishedName()
          Returns the distinguished name of the CA used to sign the newly generated certificates.
static java.lang.String getCertificateDistinguishedName(java.io.InputStream keystore, java.lang.String password, java.lang.String alias, boolean useBCAPI)
          This is a helper function for fetching the distinguished name from a certificate.
static int getCertificateValidity(java.io.InputStream keystore, java.lang.String password, java.lang.String alias, boolean useBCAPI)
          This is a helper function for fetching the validity from a certificate.
static void main(java.lang.String[] args)
          The test CA can e.g. be created with Hmm, this CA doesn't work - look at the Javadoc comment for the constructor for how to create it correctly.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CertificateSignatureAlgorithm

public static final java.lang.String CertificateSignatureAlgorithm
This method is used for signing the certificate.

See Also:
Constant Field Values

CertificateExportFriendlyName

public static final java.lang.String CertificateExportFriendlyName
This string is used as the friendly name for the certificate in the PKCS12 exported file.

See Also:
Constant Field Values

KeyExportFriendlyName

public static final java.lang.String KeyExportFriendlyName
This string is used as the friendly name for the private key in the PKCS12 exported file.

See Also:
Constant Field Values
Constructor Detail

X509CertificateGenerator

protected X509CertificateGenerator(boolean useBCAPI)
Initializes the objects without an existing CA. This is useful to create a new CA, because createCertificate will create a self-signed certificate if no CA has been set. This constructor is used by createNewCa.

Parameters:
useBCAPI - Set to true if the Bouncycastle lightweight API should be used for cryptographical operations. If set to false, the JCE infrastructure with the configured default provider will be used. JCE may be faster depending on the provider implementation, but it might not be available on embedded platforms, i.e. J2ME.
See Also:
createNewCa(java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean), createCertificate(String, int, String, String, String)

X509CertificateGenerator

public X509CertificateGenerator(java.lang.String caFile,
                                java.lang.String caPassword,
                                java.lang.String caAlias,
                                boolean useBCAPI)
                         throws java.security.NoSuchAlgorithmException,
                                java.security.cert.CertificateException,
                                java.io.FileNotFoundException,
                                java.io.IOException,
                                java.security.InvalidKeyException,
                                java.security.NoSuchProviderException,
                                java.security.SignatureException
Initializes the object for creating certificates by loading the CA certificate and private key. A new CA can be created with: Comment out basicConstraints in /etc/ssl/openssl.cnf (CA:FALSE should not be set, but it does not need to be set to true) /usr/lib/ssl/misc/CA.sh -newca openssl pkcs12 -export -in demoCA/cacert.pem -inkey demoCA/private/cakey.pem -out ca.p12 -name "Test CA"

Parameters:
caFile - The PKCS12 encoded file containing the whole CA to use. It must contain the CA certificate (which will be self-signed for top-level CAs) and the matching private key.
caPassword - The password necessary to decode the PKCS12 file.
caAlias - The friendly name of the CA in the PKCS12 file.
useBCAPI - Set to true if the Bouncycastle lightweight API should be used for cryptographical operations. If set to false, the JCE infrastructure with the configured default provider will be used. JCE may be faster depending on the provider implementation, but it might not be available on embedded platforms, i.e. J2ME.
Throws:
java.security.NoSuchAlgorithmException
java.security.cert.CertificateException
java.io.FileNotFoundException
java.io.IOException
java.security.InvalidKeyException
java.security.NoSuchProviderException
java.security.SignatureException
Method Detail

createNewCa

public static boolean createNewCa(java.lang.String commonName,
                                  int validityDays,
                                  java.lang.String caFile,
                                  java.lang.String caPassword,
                                  java.lang.String caAlias,
                                  boolean useBCAPI)
                           throws java.security.InvalidKeyException,
                                  org.bouncycastle.crypto.DataLengthException,
                                  java.lang.SecurityException,
                                  java.security.SignatureException,
                                  java.security.NoSuchAlgorithmException,
                                  java.security.KeyStoreException,
                                  java.security.cert.CertificateException,
                                  java.security.spec.InvalidKeySpecException,
                                  java.io.IOException,
                                  org.bouncycastle.crypto.CryptoException
Creates a new self-signed CA (certificate authority) for subsequently signing certificates.

Parameters:
commonName - The common name (CN) field of the X.509 distinguished name that should be set for the new certificate. All other fields of the distinguished name are not set.
validityDays - How long the new certificate should be valid, in days.
caFile - The PKCS12 encoded file to which the CA should be exported to. It will contain the self-signed certificate and the matching private key.
caPassword - The password used to encode the PKCS12 file.
caAlias - The friendly name of the CA in the PKCS12 file.
useBCAPI - Set to true if the Bouncycastle lightweight API should be used for cryptographical operations. If set to false, the JCE infrastructure with the configured default provider will be used. JCE may be faster depending on the provider implementation, but it might not be available on embedded platforms, i.e. J2ME.
Returns:
true if the CA could be created, self-signed, and exported successfully, false otherwise.
Throws:
org.bouncycastle.crypto.CryptoException
java.io.IOException
java.security.spec.InvalidKeySpecException
java.security.cert.CertificateException
java.security.NoSuchProviderException
java.security.KeyStoreException
java.security.NoSuchAlgorithmException
java.security.SignatureException
java.lang.SecurityException
org.bouncycastle.crypto.DataLengthException
java.security.InvalidKeyException

convertPKCS12toPEM

public static boolean convertPKCS12toPEM(java.lang.String inFile,
                                         java.lang.String inPassword,
                                         java.lang.String outCertFile,
                                         java.lang.String outKeyFile,
                                         java.lang.String outCertChainFile,
                                         boolean useBCAPI)
Converts from a PKCS12 encoded file to PEM encoded files readable by openssl (and subsequently e.g. openswan and racoon).

Parameters:
inFile - The PKCS12 encoded input file. It is assumed to contain the (client) certificate, the matching private key, and the complete certificate chain up to the self-signed root CA.
inPassword - The password needed to decrypt the PKCS12 encoded input file.
outCertFile - The output certificate in PEM format. If null, it will not be created.
outKeyFile - The output private key in PEM format. If null, it will not be created.
outCertChainFile - The output certificate chain in PEM format. If null, it will not be created.
useBCAPI - Set to true if the Bouncycastle lightweight API should be used for cryptographical operations. If set to false, the JCE infrastructure with the configured default provider will be used. JCE may be faster depending on the provider implementation, but it might not be available on embedded platforms, i.e. J2ME.
Returns:
true if all requested parts could be exported successfully, false otherwise.

getCaDistinguishedName

public java.lang.String getCaDistinguishedName()
Returns the distinguished name of the CA used to sign the newly generated certificates. This is important e.g. when using the new certificates for IPSec connections under Windows 2000/XP, because the CA DN must be specified for such connections.

Returns:
The CA DN.

createCertificate

public boolean createCertificate(java.lang.String commonName,
                                 int validityDays,
                                 java.lang.String exportFile,
                                 java.lang.String exportPassword)
                          throws java.io.IOException,
                                 java.security.InvalidKeyException,
                                 java.lang.SecurityException,
                                 java.security.SignatureException,
                                 java.security.NoSuchAlgorithmException,
                                 org.bouncycastle.crypto.DataLengthException,
                                 org.bouncycastle.crypto.CryptoException,
                                 java.security.KeyStoreException,
                                 java.security.cert.CertificateException,
                                 java.security.spec.InvalidKeySpecException
This method should create something similar to: openssl req -new -outform PEM -newkey rsa:1024 -nodes -keyout /tmp/test.key -keyform PEM -out /tmp/test.pem -days 30 -config /etc/ssl/openssl.cnf openssl ca -policy policy_anything -out /tmp/test.crt -config /etc/ssl/openssl.cnf -infiles /tmp/test.pem openssl pkcs12 -export -in /tmp/test.crt -inkey /tmp/test.key -certfile demoCA/cacert.pem -out test.p12

Parameters:
commonName - The common name (CN) field of the X.509 distinguished name that should be set for the new certificate. All other fields of the distinguished name are not set.
validityDays - How long the new certificate should be valid, in days.
exportFile - The PKCS12 encoded file to which the certificate should be exported to. It will contain the self-signed certificate and the matching private key.
exportPassword - The password used to encode the PKCS12 file.
Returns:
true if the certificate could be created, signed, and exported successfully, false otherwise.
Throws:
java.io.IOException
java.security.InvalidKeyException
java.lang.SecurityException
java.security.SignatureException
java.security.NoSuchAlgorithmException
org.bouncycastle.crypto.DataLengthException
org.bouncycastle.crypto.CryptoException
java.security.KeyStoreException
java.security.cert.CertificateException
java.security.spec.InvalidKeySpecException

createCertificate

protected boolean createCertificate(java.lang.String commonName,
                                    int validityDays,
                                    java.lang.String exportFile,
                                    java.lang.String exportPassword,
                                    java.lang.String exportAlias)
                             throws java.io.IOException,
                                    java.security.InvalidKeyException,
                                    java.lang.SecurityException,
                                    java.security.SignatureException,
                                    java.security.NoSuchAlgorithmException,
                                    org.bouncycastle.crypto.DataLengthException,
                                    org.bouncycastle.crypto.CryptoException,
                                    java.security.KeyStoreException,
                                    java.security.cert.CertificateException,
                                    java.security.spec.InvalidKeySpecException
This method implements the public one, but offers an additional parameter which is only used when creating a new CA, namely the export alias to use.

Parameters:
commonName - @see #createCertificate(String, int, String, String)
validityDays - @see #createCertificate(String, int, String, String)
exportFile - @see #createCertificate(String, int, String, String)
exportPassword - @see #createCertificate(String, int, String, String)
exportAlias - If this additional parameter is null, a default value will be used as the "friendly name" in the PKCS12 file.
Returns:
@see #createCertificate(String, int, String, String)
Throws:
java.io.IOException
java.security.InvalidKeyException
java.lang.SecurityException
java.security.SignatureException
java.security.NoSuchAlgorithmException
org.bouncycastle.crypto.DataLengthException
org.bouncycastle.crypto.CryptoException
java.security.KeyStoreException
java.security.cert.CertificateException
java.security.spec.InvalidKeySpecException
See Also:
X509CertificateGenerator(boolean)

getCertificateDistinguishedName

public static java.lang.String getCertificateDistinguishedName(java.io.InputStream keystore,
                                                               java.lang.String password,
                                                               java.lang.String alias,
                                                               boolean useBCAPI)
This is a helper function for fetching the distinguished name from a certificate.

Parameters:
keystore - The keystore/PKCS12 file to load from.
password - The password used to encrypt the keystore/PKCS12 file.
alias - The alias used to store the certificate in the keystore/PKCS12 file.
useBCAPI - Set to true if the Bouncycastle API should be used instead of JCE.
Returns:
The subject DN if the certificate could be successfully loaded, null otherwise.

getCertificateValidity

public static int getCertificateValidity(java.io.InputStream keystore,
                                         java.lang.String password,
                                         java.lang.String alias,
                                         boolean useBCAPI)
This is a helper function for fetching the validity from a certificate.

Parameters:
keystore - The keystore/PKCS12 file to load from.
password - The password used to encrypt the keystore/PKCS12 file.
alias - The alias used to store the certificate in the keystore/PKCS12 file.
useBCAPI - Set to true if the Bouncycastle API should be used instead of JCE.
Returns:
The validity in days (from now) if the certificate could be loaded successfully, -1 otherwise

main

public static void main(java.lang.String[] args)
                 throws java.lang.Exception
The test CA can e.g. be created with Hmm, this CA doesn't work - look at the Javadoc comment for the constructor for how to create it correctly. echo -e "AT\nUpper Austria\nSteyr\nMy Organization\nNetwork tests\nTest CA certificate\nme@myserver.com\n\n\n" | \ openssl req -new -x509 -outform PEM -newkey rsa:2048 -nodes -keyout /tmp/ca.key -keyform PEM -out /tmp/ca.crt -days 365; echo "test password" | openssl pkcs12 -export -in /tmp/ca.crt -inkey /tmp/ca.key -out ca.p12 -name "Test CA" -passout stdin The created certificate can be displayed with openssl pkcs12 -nodes -info -in test.p12 > /tmp/test.cert && openssl x509 -noout -text -in /tmp/test.cert

Parameters:
args -
Throws:
java.lang.Exception


2005-2006, Rene Mayrhofer.