|  | @@ -25,18 +25,13 @@ import java.io.ByteArrayInputStream;
 | 
	
		
			
				|  |  |  import java.io.FileNotFoundException;
 | 
	
		
			
				|  |  |  import java.io.IOException;
 | 
	
		
			
				|  |  |  import java.io.InputStream;
 | 
	
		
			
				|  |  | -import java.io.InputStreamReader;
 | 
	
		
			
				|  |  |  import java.io.Reader;
 | 
	
		
			
				|  |  |  import java.io.StringReader;
 | 
	
		
			
				|  |  | -import java.io.StringWriter;
 | 
	
		
			
				|  |  | -import java.math.BigInteger;
 | 
	
		
			
				|  |  |  import java.net.URL;
 | 
	
		
			
				|  |  |  import java.security.GeneralSecurityException;
 | 
	
		
			
				|  |  |  import java.security.InvalidKeyException;
 | 
	
		
			
				|  |  |  import java.security.KeyStore;
 | 
	
		
			
				|  |  |  import java.security.KeyStoreException;
 | 
	
		
			
				|  |  | -import java.security.PrivateKey;
 | 
	
		
			
				|  |  | -import java.security.PublicKey;
 | 
	
		
			
				|  |  |  import java.security.Security;
 | 
	
		
			
				|  |  |  import java.security.SignatureException;
 | 
	
		
			
				|  |  |  import java.security.cert.Certificate;
 | 
	
	
		
			
				|  | @@ -48,27 +43,12 @@ import java.text.MessageFormat;
 | 
	
		
			
				|  |  |  import java.util.ArrayList;
 | 
	
		
			
				|  |  |  import java.util.Arrays;
 | 
	
		
			
				|  |  |  import java.util.Collection;
 | 
	
		
			
				|  |  | -import java.util.Date;
 | 
	
		
			
				|  |  |  import java.util.Enumeration;
 | 
	
		
			
				|  |  | -import java.util.Hashtable;
 | 
	
		
			
				|  |  |  import java.util.List;
 | 
	
		
			
				|  |  | -import java.util.Vector;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  import javax.security.auth.x500.X500Principal;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import org.apache.commons.codec.binary.Base64;
 | 
	
		
			
				|  |  | -import org.bouncycastle.asn1.DERObjectIdentifier;
 | 
	
		
			
				|  |  | -import org.bouncycastle.asn1.x500.X500Name;
 | 
	
		
			
				|  |  | -import org.bouncycastle.asn1.x509.X509Name;
 | 
	
		
			
				|  |  | -import org.bouncycastle.cert.X509v3CertificateBuilder;
 | 
	
		
			
				|  |  | -import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
 | 
	
		
			
				|  |  | -import org.bouncycastle.jce.PKCS10CertificationRequest;
 | 
	
		
			
				|  |  | -import org.bouncycastle.jce.PrincipalUtil;
 | 
	
		
			
				|  |  | -import org.bouncycastle.jce.X509Principal;
 | 
	
		
			
				|  |  |  import org.bouncycastle.openssl.PEMParser;
 | 
	
		
			
				|  |  | -import org.bouncycastle.openssl.PEMWriter;
 | 
	
		
			
				|  |  | -import org.bouncycastle.openssl.PasswordException;
 | 
	
		
			
				|  |  | -import org.bouncycastle.x509.X509V3CertificateGenerator;
 | 
	
		
			
				|  |  |  import org.slf4j.Logger;
 | 
	
		
			
				|  |  |  import org.slf4j.LoggerFactory;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -82,16 +62,16 @@ public final class X509CertUtils {
 | 
	
		
			
				|  |  |  	// Logger.getLogger(X509CertUtil.class.getCanonicalName());
 | 
	
		
			
				|  |  |  	private static final Logger _logger = LoggerFactory.getLogger(X509CertUtils.class);
 | 
	
		
			
				|  |  |  	/** PKCS #7 encoding name */
 | 
	
		
			
				|  |  | -	private static final String PKCS7_ENCODING = "PKCS7";
 | 
	
		
			
				|  |  | +	public static final String PKCS7_ENCODING = "PKCS7";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/** PkiPath encoding name */
 | 
	
		
			
				|  |  | -	private static final String PKIPATH_ENCODING = "PkiPath";
 | 
	
		
			
				|  |  | +	public static final String PKIPATH_ENCODING = "PkiPath";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/** OpenSSL PEM encoding name */
 | 
	
		
			
				|  |  | -	private static final String OPENSSL_PEM_ENCODING = "OpenSSL_PEM";
 | 
	
		
			
				|  |  | +	public static final String OPENSSL_PEM_ENCODING = "OpenSSL_PEM";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/** Type name for X.509 certificates */
 | 
	
		
			
				|  |  | -	private static final String X509_CERT_TYPE = "X.509";
 | 
	
		
			
				|  |  | +	public static final String X509_CERT_TYPE = "X.509";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/**
 | 
	
		
			
				|  |  |  	 * Private to prevent construction.
 | 
	
	
		
			
				|  | @@ -100,40 +80,7 @@ public final class X509CertUtils {
 | 
	
		
			
				|  |  |  		// Nothing to do
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Load one or more certificates from the specified URL, trying a built in
 | 
	
		
			
				|  |  | -	 * list of certification encodings.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @param url
 | 
	
		
			
				|  |  | -	 *            The URL to load certificates from
 | 
	
		
			
				|  |  | -	 * @param exceptions
 | 
	
		
			
				|  |  | -	 *            Collection where exceptions occurred will be added
 | 
	
		
			
				|  |  | -	 * @return The certificates
 | 
	
		
			
				|  |  | -	 * @throws IOException
 | 
	
		
			
				|  |  | -	 *             if an error accessing the URL occurs
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	public static X509Certificate[] loadCertificates(URL url,
 | 
	
		
			
				|  |  | -			Collection<Exception> exceptions) throws IOException {
 | 
	
		
			
				|  |  | -		URL downloadedUrl = NetUtil.download(url);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		X509Certificate[] certs = null;
 | 
	
		
			
				|  |  | -		for (String certType : new String[] { PKCS7_ENCODING, PKIPATH_ENCODING,
 | 
	
		
			
				|  |  | -				null, OPENSSL_PEM_ENCODING }) {
 | 
	
		
			
				|  |  | -			try {
 | 
	
		
			
				|  |  | -				certs = loadCertificates(downloadedUrl, certType);
 | 
	
		
			
				|  |  | -				break; // Success!
 | 
	
		
			
				|  |  | -			} catch (FileNotFoundException e) {
 | 
	
		
			
				|  |  | -				// Don't bother with rest of the types, just show the exception
 | 
	
		
			
				|  |  | -				// once
 | 
	
		
			
				|  |  | -				exceptions.add(e);
 | 
	
		
			
				|  |  | -				break;
 | 
	
		
			
				|  |  | -			} catch (Exception e) {
 | 
	
		
			
				|  |  | -				exceptions.add(e);
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		return certs;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	public static X509Certificate loadCertFromPEM(String strPEM) {
 | 
	
		
			
				|  |  |  		StringReader stringReader = new StringReader(strPEM);
 | 
	
	
		
			
				|  | @@ -179,109 +126,7 @@ public final class X509CertUtils {
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Load one or more certificates from the specified URL.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @param url
 | 
	
		
			
				|  |  | -	 *            The URL to load certificates from
 | 
	
		
			
				|  |  | -	 * @param encoding
 | 
	
		
			
				|  |  | -	 *            The certification path encoding. If null, treat as a normal
 | 
	
		
			
				|  |  | -	 *            certificate, not certification path. Use one of the
 | 
	
		
			
				|  |  | -	 *            <code>*_ENCODING</code> constants here.
 | 
	
		
			
				|  |  | -	 * @return The certificates
 | 
	
		
			
				|  |  | -	 * @throws CryptoException
 | 
	
		
			
				|  |  | -	 *             Problem encountered while loading the certificate(s)
 | 
	
		
			
				|  |  | -	 * @throws FileNotFoundException
 | 
	
		
			
				|  |  | -	 *             If the certificate file does not exist, is a directory rather
 | 
	
		
			
				|  |  | -	 *             than a regular file, or for some other reason cannot be
 | 
	
		
			
				|  |  | -	 *             opened for reading
 | 
	
		
			
				|  |  | -	 * @throws IOException
 | 
	
		
			
				|  |  | -	 *             An I/O error occurred
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	private static X509Certificate[] loadCertificates(URL url, String encoding)
 | 
	
		
			
				|  |  | -			throws CryptoException, IOException {
 | 
	
		
			
				|  |  | -		// TODO: connect/read timeouts
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		InputStream in = NetUtil.openGetStream(url);
 | 
	
		
			
				|  |  | -		Collection certs;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		try {
 | 
	
		
			
				|  |  | -			if (OPENSSL_PEM_ENCODING.equals(encoding)) {
 | 
	
		
			
				|  |  | -				// Special case; this is not a real JCE supported encoding.
 | 
	
		
			
				|  |  | -				// Note: let PEMReader use its default provider (BC as of BC
 | 
	
		
			
				|  |  | -				// 1.40) internally; for example the
 | 
	
		
			
				|  |  | -				// default "SUN" provider may not contain an RSA implementation
 | 
	
		
			
				|  |  | -				PEMParser pr = new PEMParser(new InputStreamReader(in));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				// These beasts can contain just about anything, and
 | 
	
		
			
				|  |  | -				// unfortunately the PEMReader API (as of BC
 | 
	
		
			
				|  |  | -				// 1.25 to at least 1.43) won't allow us to really skip things
 | 
	
		
			
				|  |  | -				// we're not interested in; stuff
 | 
	
		
			
				|  |  | -				// happens already in readObject().
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				certs = new ArrayList<X509Certificate>();
 | 
	
		
			
				|  |  | -				Object cert;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				while (true) {
 | 
	
		
			
				|  |  | -					try {
 | 
	
		
			
				|  |  | -						cert = pr.readObject();
 | 
	
		
			
				|  |  | -					} catch (IOException e) {
 | 
	
		
			
				|  |  | -						if (e instanceof PasswordException) {
 | 
	
		
			
				|  |  | -							// Some kind of a password protected item (BC >=
 | 
	
		
			
				|  |  | -							// 1.44): carry on, see
 | 
	
		
			
				|  |  | -							// http://www.bouncycastle.org/jira/browse/BJA-182
 | 
	
		
			
				|  |  | -							continue;
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -						throw e;
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -					if (cert == null) {
 | 
	
		
			
				|  |  | -						break;
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -					if (cert instanceof X509Certificate) {
 | 
	
		
			
				|  |  | -						certs.add(cert);
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					// Skip other stuff, at least for now.
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				pr.close();
 | 
	
		
			
				|  |  | -			} else {
 | 
	
		
			
				|  |  | -				CertificateFactory cf = CertificateFactory
 | 
	
		
			
				|  |  | -						.getInstance(X509_CERT_TYPE);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				if (encoding != null) {
 | 
	
		
			
				|  |  | -					// Try it as a certification path of the specified type
 | 
	
		
			
				|  |  | -					certs = cf.generateCertPath(in, encoding).getCertificates();
 | 
	
		
			
				|  |  | -				} else {
 | 
	
		
			
				|  |  | -					// "Normal" certificate(s)
 | 
	
		
			
				|  |  | -					certs = cf.generateCertificates(in);
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				// Note that we rely on cf.generateCert() above to never return
 | 
	
		
			
				|  |  | -				// null nor a collection
 | 
	
		
			
				|  |  | -				// containing nulls.
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		// Some RuntimeExceptions which really should be CertificateExceptions
 | 
	
		
			
				|  |  | -		// may be thrown from
 | 
	
		
			
				|  |  | -		// cf.generateCert* above, for example Oracle's PKCS #7 parser tends to
 | 
	
		
			
				|  |  | -		// throw them... :P
 | 
	
		
			
				|  |  | -		catch (Exception ex) {
 | 
	
		
			
				|  |  | -			// TODO: don't throw if vCerts non-empty (eg. OpenSSL PEM above)?
 | 
	
		
			
				|  |  | -			throw new CryptoException("Could not load certificate.", ex);
 | 
	
		
			
				|  |  | -		} finally {
 | 
	
		
			
				|  |  | -			try {
 | 
	
		
			
				|  |  | -				in.close();
 | 
	
		
			
				|  |  | -			} catch (IOException e) {
 | 
	
		
			
				|  |  | -				_logger.warn("Could not close input stream from " + url, e);
 | 
	
		
			
				|  |  | -				// LOG.log(Level.WARNING, "Could not close input stream from " +
 | 
	
		
			
				|  |  | -				// url, e);
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		return (X509Certificate[]) certs.toArray(new X509Certificate[certs.size()]);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/**
 | 
	
		
			
				|  |  |  	 * Load a CRL from the specified URL.
 | 
	
	
		
			
				|  | @@ -318,50 +163,7 @@ public final class X509CertUtils {
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Load a CSR from the specified URL.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @param url
 | 
	
		
			
				|  |  | -	 *            The URL to load CSR from
 | 
	
		
			
				|  |  | -	 * @return The CSR
 | 
	
		
			
				|  |  | -	 * @throws CryptoException
 | 
	
		
			
				|  |  | -	 *             Problem encountered while loading the CSR
 | 
	
		
			
				|  |  | -	 * @throws FileNotFoundException
 | 
	
		
			
				|  |  | -	 *             If the CSR file does not exist, is a directory rather than a
 | 
	
		
			
				|  |  | -	 *             regular file, or for some other reason cannot be opened for
 | 
	
		
			
				|  |  | -	 *             reading
 | 
	
		
			
				|  |  | -	 * @throws IOException
 | 
	
		
			
				|  |  | -	 *             An I/O error occurred
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	public static PKCS10CertificationRequest loadCSR(URL url)
 | 
	
		
			
				|  |  | -			throws CryptoException, IOException {
 | 
	
		
			
				|  |  | -		// TODO: handle DER encoded requests too?
 | 
	
		
			
				|  |  | -		PEMParser pr = new PEMParser(new InputStreamReader(
 | 
	
		
			
				|  |  | -				NetUtil.openGetStream(url)));
 | 
	
		
			
				|  |  | -		try {
 | 
	
		
			
				|  |  | -			PKCS10CertificationRequest csr = (PKCS10CertificationRequest) pr
 | 
	
		
			
				|  |  | -					.readObject();
 | 
	
		
			
				|  |  | -			if (!csr.verify()) {
 | 
	
		
			
				|  |  | -				throw new CryptoException(
 | 
	
		
			
				|  |  | -						"Could not verify certification request.");
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -			return csr;
 | 
	
		
			
				|  |  | -		} catch (ClassCastException ex) {
 | 
	
		
			
				|  |  | -			throw new CryptoException("Could not load certification request.",
 | 
	
		
			
				|  |  | -					ex);
 | 
	
		
			
				|  |  | -		} catch (GeneralSecurityException ex) {
 | 
	
		
			
				|  |  | -			throw new CryptoException("Could not load certification request.",
 | 
	
		
			
				|  |  | -					ex);
 | 
	
		
			
				|  |  | -		} finally {
 | 
	
		
			
				|  |  | -			try {
 | 
	
		
			
				|  |  | -				pr.close();
 | 
	
		
			
				|  |  | -			} catch (IOException e) {
 | 
	
		
			
				|  |  | -				_logger.warn("Could not close input stream from " + url, e);
 | 
	
		
			
				|  |  | -				// LOG.log(Level.WARNING, "Could not close input stream from " +
 | 
	
		
			
				|  |  | -				// url, e);
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/**
 | 
	
		
			
				|  |  |  	 * Convert the supplied array of certificate objects into X509Certificate
 | 
	
	
		
			
				|  | @@ -574,248 +376,7 @@ public final class X509CertUtils {
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Generate a self-signed X509 Version 1 certificate for the supplied key
 | 
	
		
			
				|  |  | -	 * pair and signature algorithm.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @return The generated certificate
 | 
	
		
			
				|  |  | -	 * @param sCommonName
 | 
	
		
			
				|  |  | -	 *            Common name certificate attribute
 | 
	
		
			
				|  |  | -	 * @param sOrganisationUnit
 | 
	
		
			
				|  |  | -	 *            Organization Unit certificate attribute
 | 
	
		
			
				|  |  | -	 * @param sOrganisation
 | 
	
		
			
				|  |  | -	 *            Organization certificate attribute
 | 
	
		
			
				|  |  | -	 * @param sLocality
 | 
	
		
			
				|  |  | -	 *            Locality certificate
 | 
	
		
			
				|  |  | -	 * @param sState
 | 
	
		
			
				|  |  | -	 *            State certificate attribute
 | 
	
		
			
				|  |  | -	 * @param sEmailAddress
 | 
	
		
			
				|  |  | -	 *            Email Address certificate attribute
 | 
	
		
			
				|  |  | -	 * @param sCountryCode
 | 
	
		
			
				|  |  | -	 *            Country Code certificate attribute
 | 
	
		
			
				|  |  | -	 * @param iValidity
 | 
	
		
			
				|  |  | -	 *            Validity period of certificate in days
 | 
	
		
			
				|  |  | -	 * @param publicKey
 | 
	
		
			
				|  |  | -	 *            Public part of key pair
 | 
	
		
			
				|  |  | -	 * @param privateKey
 | 
	
		
			
				|  |  | -	 *            Private part of key pair
 | 
	
		
			
				|  |  | -	 * @param signatureType
 | 
	
		
			
				|  |  | -	 *            Signature Type
 | 
	
		
			
				|  |  | -	 * @throws CryptoException
 | 
	
		
			
				|  |  | -	 *             If there was a problem generating the certificate
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	public static X509Certificate generateCert(String sCommonName,
 | 
	
		
			
				|  |  | -			String sOrganisationUnit, String sOrganisation, String sLocality,
 | 
	
		
			
				|  |  | -			String sState, String sCountryCode, String sEmailAddress,
 | 
	
		
			
				|  |  | -			int iValidity, PublicKey publicKey, PrivateKey privateKey,
 | 
	
		
			
				|  |  | -			SignatureType signatureType) throws CryptoException {
 | 
	
		
			
				|  |  | -		// Holds certificate attributes
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		Hashtable<DERObjectIdentifier, String> attrs = new Hashtable<DERObjectIdentifier, String>();
 | 
	
		
			
				|  |  | -		Vector<DERObjectIdentifier> vOrder = new Vector<DERObjectIdentifier>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Load certificate attributes
 | 
	
		
			
				|  |  | -		/*
 | 
	
		
			
				|  |  | -		if (sCommonName != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.CN, sCommonName);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.CN);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if (sOrganisationUnit != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.OU, sOrganisationUnit);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.OU);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if (sOrganisation != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.O, sOrganisation);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.O);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if (sLocality != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.L, sLocality);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.L);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if (sState != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.ST, sState);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.ST);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if (sCountryCode != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.C, sCountryCode);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.C);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if (sEmailAddress != null) {
 | 
	
		
			
				|  |  | -			attrs.put(X509Name.E, sEmailAddress);
 | 
	
		
			
				|  |  | -			vOrder.add(0, X509Name.E);
 | 
	
		
			
				|  |  | -		}*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Get an X509 Version 1 Certificate generator
 | 
	
		
			
				|  |  | -		X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Load the generator with generation parameters
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the issuer distinguished name
 | 
	
		
			
				|  |  | -		certGen.setIssuerDN(new X509Principal(vOrder, attrs));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Valid before and after dates now to iValidity days in the future
 | 
	
		
			
				|  |  | -		certGen.setNotBefore(new Date(System.currentTimeMillis()));
 | 
	
		
			
				|  |  | -		certGen.setNotAfter(new Date(System.currentTimeMillis()
 | 
	
		
			
				|  |  | -				+ ((long) iValidity * 24 * 60 * 60 * 1000)));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the subject distinguished name (same as issuer for our purposes)
 | 
	
		
			
				|  |  | -		certGen.setSubjectDN(new X509Principal(vOrder, attrs));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the public key
 | 
	
		
			
				|  |  | -		certGen.setPublicKey(publicKey);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the algorithm
 | 
	
		
			
				|  |  | -		certGen.setSignatureAlgorithm(signatureType.name());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the serial number
 | 
	
		
			
				|  |  | -		certGen.setSerialNumber(generateX509SerialNumber());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
 | 
	
		
			
				|  |  | -				new X500Name("issueDn"), 
 | 
	
		
			
				|  |  | -				generateX509SerialNumber(), 
 | 
	
		
			
				|  |  | -				new Date(System.currentTimeMillis()), 
 | 
	
		
			
				|  |  | -				new Date(System.currentTimeMillis()+ ((long) iValidity * 24 * 60 * 60 * 1000)), 
 | 
	
		
			
				|  |  | -				new X500Name("subjectDn"),
 | 
	
		
			
				|  |  | -				publicKey);
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  | -		try {
 | 
	
		
			
				|  |  | -			// Generate an X.509 certificate, based on the current issuer and
 | 
	
		
			
				|  |  | -			// subject
 | 
	
		
			
				|  |  | -			return certGen.generate(privateKey, "BC");
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		// Something went wrong
 | 
	
		
			
				|  |  | -		catch (GeneralSecurityException ex) {
 | 
	
		
			
				|  |  | -			throw new CryptoException("Certificate generation failed.", ex);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Renew a self-signed X509 Version 1 certificate.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @return The renewed certificate
 | 
	
		
			
				|  |  | -	 * @param oldCert
 | 
	
		
			
				|  |  | -	 *            old certificate
 | 
	
		
			
				|  |  | -	 * @param iValidity
 | 
	
		
			
				|  |  | -	 *            Validity period of certificate in days to add to the old
 | 
	
		
			
				|  |  | -	 *            cert's expiry date, or current time if the certificate has
 | 
	
		
			
				|  |  | -	 *            expired
 | 
	
		
			
				|  |  | -	 * @param publicKey
 | 
	
		
			
				|  |  | -	 *            Public part of key pair
 | 
	
		
			
				|  |  | -	 * @param privateKey
 | 
	
		
			
				|  |  | -	 *            Private part of key pair
 | 
	
		
			
				|  |  | -	 * @throws CryptoException
 | 
	
		
			
				|  |  | -	 *             If there was a problem generating the certificate
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	public static X509Certificate renewCert(X509Certificate oldCert,
 | 
	
		
			
				|  |  | -			int iValidity, PublicKey publicKey, PrivateKey privateKey)
 | 
	
		
			
				|  |  | -			throws CryptoException {
 | 
	
		
			
				|  |  | -		// Get an X509 Version 1 Certificate generator
 | 
	
		
			
				|  |  | -		X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Load the generator with generation parameters
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Valid before and after dates now to iValidity days in the future from
 | 
	
		
			
				|  |  | -		// now or existing expiry date
 | 
	
		
			
				|  |  | -		Date now = new Date();
 | 
	
		
			
				|  |  | -		Date oldExpiry = oldCert.getNotAfter();
 | 
	
		
			
				|  |  | -		if (oldExpiry == null || oldExpiry.before(now)) {
 | 
	
		
			
				|  |  | -			oldExpiry = now;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		certGen.setNotBefore(now);
 | 
	
		
			
				|  |  | -		certGen.setNotAfter(new Date(oldExpiry.getTime()
 | 
	
		
			
				|  |  | -				+ ((long) iValidity * 24 * 60 * 60 * 1000)));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the public key
 | 
	
		
			
				|  |  | -		certGen.setPublicKey(publicKey);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the algorithm
 | 
	
		
			
				|  |  | -		certGen.setSignatureAlgorithm(oldCert.getSigAlgName());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// Set the serial number
 | 
	
		
			
				|  |  | -		certGen.setSerialNumber(generateX509SerialNumber());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		try {
 | 
	
		
			
				|  |  | -			// Set the issuer distinguished name
 | 
	
		
			
				|  |  | -			// TODO: verify/force self-signedness
 | 
	
		
			
				|  |  | -			certGen.setIssuerDN(PrincipalUtil.getIssuerX509Principal(oldCert));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			// Set the subject distinguished name (same as issuer for our
 | 
	
		
			
				|  |  | -			// purposes)
 | 
	
		
			
				|  |  | -			certGen.setSubjectDN(PrincipalUtil.getSubjectX509Principal(oldCert));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			// Generate an X.509 certificate, based on the current issuer and
 | 
	
		
			
				|  |  | -			// subject
 | 
	
		
			
				|  |  | -			return certGen.generate(privateKey, "BC");
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		// Something went wrong
 | 
	
		
			
				|  |  | -		catch (GeneralSecurityException ex) {
 | 
	
		
			
				|  |  | -			throw new CryptoException("Certificate generation failed.", ex);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Generate a unique serial number for use as an X509 serial number.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @return The unique serial number
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	private static BigInteger generateX509SerialNumber() {
 | 
	
		
			
				|  |  | -		// Time in seconds
 | 
	
		
			
				|  |  | -		return new BigInteger(Long.toString(System.currentTimeMillis() / 1000));
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	public static String generatePEMEncoded(Certificate cert) {
 | 
	
		
			
				|  |  | -		StringWriter encoded = new StringWriter();
 | 
	
		
			
				|  |  | -		PEMWriter pEMWriter = new PEMWriter(encoded);
 | 
	
		
			
				|  |  | -		try {
 | 
	
		
			
				|  |  | -			pEMWriter.writeObject(cert);
 | 
	
		
			
				|  |  | -			pEMWriter.close();
 | 
	
		
			
				|  |  | -			return encoded.toString();
 | 
	
		
			
				|  |  | -		} catch (IOException e) {
 | 
	
		
			
				|  |  | -			e.printStackTrace();
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		return null;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	/**
 | 
	
		
			
				|  |  | -	 * Create a PKCS #10 certification request (CSR) using the supplied
 | 
	
		
			
				|  |  | -	 * certificate and private key.
 | 
	
		
			
				|  |  | -	 * 
 | 
	
		
			
				|  |  | -	 * @param cert
 | 
	
		
			
				|  |  | -	 *            The certificate
 | 
	
		
			
				|  |  | -	 * @param privateKey
 | 
	
		
			
				|  |  | -	 *            The private key
 | 
	
		
			
				|  |  | -	 * @throws CryptoException
 | 
	
		
			
				|  |  | -	 *             If there was a problem generating the CSR
 | 
	
		
			
				|  |  | -	 * @return The CSR
 | 
	
		
			
				|  |  | -	 */
 | 
	
		
			
				|  |  | -	public static PKCS10CertificationRequest generatePKCS10CSR(
 | 
	
		
			
				|  |  | -			X509Certificate cert, PrivateKey privateKey) throws CryptoException {
 | 
	
		
			
				|  |  | -		X509Name subject = new X509Name(cert.getSubjectDN().toString());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		try {
 | 
	
		
			
				|  |  | -			PKCS10CertificationRequest csr = new PKCS10CertificationRequest(
 | 
	
		
			
				|  |  | -					cert.getSigAlgName(), subject, cert.getPublicKey(), null,
 | 
	
		
			
				|  |  | -					privateKey);
 | 
	
		
			
				|  |  | -			if (!csr.verify()) {
 | 
	
		
			
				|  |  | -				throw new CryptoException(
 | 
	
		
			
				|  |  | -						"Could not verify generated certification request.");
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			return csr;
 | 
	
		
			
				|  |  | -		} catch (GeneralSecurityException ex) {
 | 
	
		
			
				|  |  | -			throw new CryptoException(
 | 
	
		
			
				|  |  | -					"Could not generate a certification request.", ex);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/**
 | 
	
		
			
				|  |  |  	 * Verify that one X.509 certificate was signed using the private key that
 | 
	
	
		
			
				|  | @@ -1008,22 +569,42 @@ public final class X509CertUtils {
 | 
	
		
			
				|  |  |  		X500Principal subject = cert.getSubjectX500Principal();
 | 
	
		
			
				|  |  |  		X500Principal issuer = cert.getIssuerX500Principal();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		String sSubjectCN = NameUtil.getCommonName(subject);
 | 
	
		
			
				|  |  | +		String sSubjectCN = getCommonName(subject);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		// Could not get a subject CN - return blank
 | 
	
		
			
				|  |  |  		if (sSubjectCN == null) {
 | 
	
		
			
				|  |  |  			return "";
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		String sIssuerCN = NameUtil.getCommonName(issuer);
 | 
	
		
			
				|  |  | +		String sIssuerCN = getCommonName(issuer);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		// Self-signed certificate or could not get an issuer CN
 | 
	
		
			
				|  |  |  		if (subject.equals(issuer) || sIssuerCN == null) {
 | 
	
		
			
				|  |  |  			// Alias is the subject CN
 | 
	
		
			
				|  |  |  			return sSubjectCN;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | +		_logger.debug("{0} ({1})", sSubjectCN, sIssuerCN);
 | 
	
		
			
				|  |  |  		// else non-self-signed certificate
 | 
	
		
			
				|  |  |  		// Alias is the subject CN followed by the issuer CN in parenthesis
 | 
	
		
			
				|  |  |  		return MessageFormat.format("{0} ({1})", sSubjectCN, sIssuerCN);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	public static String getCommonName(X500Principal name) {
 | 
	
		
			
				|  |  | +        if (name == null) {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        String value = name.getName();
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        if(value.indexOf(",") > -1) {
 | 
	
		
			
				|  |  | +            value = value.split(",")[0];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        if(value.indexOf("=")>-1) {
 | 
	
		
			
				|  |  | +            value = value.split("=")[1];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        return value;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  |  }
 |