package sernet.verinice.encryption.impl.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
*
* Utility class for certificate handling.
*
*
* Certificates, or to be more specific, public key certificates, provide a mechanism
* that allows a third party, or issuer, to vouch for the fact that a particular public key
* is linked with a particular owner, or subject.
* (from David Hook's book "Beginning Cryptography with Java")
*
*
* Requires the BouncyCastle provider library on the classpath.
*
*
* @author Sebastian Engel
*
*/
public class CertificateUtils {
private static final Logger LOG = Logger.getLogger(CertificateUtils.class);
// Add the BouncyCastle security provider if not available yet
static {
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
}
/**
* Loads a X.509 certificate from the given file.
*
* @param x509CertificateFile
* the X.509 certificate file to load
*
* @throws IOException
*
* - if the given file does not exist
* - if the given file is cannot be read
*
* @throws CertificateNotYetValidException
* if the certificate is not yet valid
* @throws CertificateExpiredException
* if the certificate is not valid anymore
* @throws CertificateException
*
* - if the given file is not a certificate file
* - if the certificate contained in the given file is not a X.509 certificate
*
*/
public static X509Certificate loadX509CertificateFromFile(File x509CertificateFile) throws IOException,
CertificateNotYetValidException, CertificateExpiredException, CertificateException {
// Check availablity and readability of the given file first
if (!x509CertificateFile.exists()) {
String message = "The given file \"" + x509CertificateFile + "\" does not exist.";
LOG.error(message);
throw new IOException(message);
} else if (!x509CertificateFile.canRead()) {
String message = "The given file \"" + x509CertificateFile + "\" cannot be read.";
LOG.error(message);
throw new IOException(message);
}
// Since the file seems to be ok, try to make a X509 certificate from it.
CertificateFactory certificateFactory = null;
try {
certificateFactory = CertificateFactory.getInstance("X.509",BouncyCastleProvider.PROVIDER_NAME);
} catch (NoSuchProviderException e) {
// Shouldn't happen, since the BouncyCastle provider was added on class loading
// or even before
LOG.error("Certificate provider not found.", e);
throw new RuntimeException("Certificate provider not found.", e);
}
Certificate certificate = certificateFactory.generateCertificate(new FileInputStream(x509CertificateFile));
if (certificate == null) {
String message = "The given file \"" + x509CertificateFile + "\" does not contain a X.509 certificate.";
LOG.error(message);
throw new CertificateException(message);
}
if (!certificate.getType().equalsIgnoreCase("x.509")) {
String message = "The certificate contained in the given file \"" + x509CertificateFile + "\" is not a X.509 certificate.";
LOG.error(message);
throw new CertificateException(message);
}
X509Certificate x509Certificate = (X509Certificate) certificate;
// Lastly checks if the certificate is (still) valid.
// If not this throws a CertificateExpiredException or
// CertificateNotYetValidException respectively.
x509Certificate.checkValidity();
return x509Certificate;
}
}