Java tutorial
/* * Copyright 1999-2010 University of Chicago * * 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.globus.gsi.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.List; import java.util.Vector; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Base64; /** * Contains various security-related utility methods. */ public final class CertificateLoadUtil { static { Security.addProvider(new BouncyCastleProvider()); logger = LogFactory.getLog(CertificateLoadUtil.class.getCanonicalName()); setProvider("BC"); } private static Log logger; private static String provider; private CertificateLoadUtil() { //This should not be created. } /** * A no-op function that can be used to force the class to load and * initialize. */ public static void init() { } /** * Sets a provider name to use for loading certificates and for generating * key pairs. * * @param providerName provider name to use. */ public static void setProvider(String providerName) { provider = providerName; logger.debug("Provider set to : " + providerName); } /** * Returns appropriate <code>CertificateFactory</code>. If <I>provider</I> * was set a provider-specific <code>CertificateFactory</code> will be used. * Otherwise, a default <code>CertificateFactory</code> will be used. * * @return <code>CertificateFactory</code> */ protected static CertificateFactory getCertificateFactory() throws GeneralSecurityException { if (provider == null) { return CertificateFactory.getInstance("X.509"); } else { return CertificateFactory.getInstance("X.509", provider); } } /** * Loads a X509 certificate from the specified input stream. Input stream * must contain DER-encoded certificate. * * @param in the input stream to read the certificate from. * @return <code>X509Certificate</code> the loaded certificate. * @throws GeneralSecurityException if certificate failed to load. */ public static X509Certificate loadCertificate(InputStream in) throws GeneralSecurityException { return (X509Certificate) getCertificateFactory().generateCertificate(in); } /** * Loads an X.509 certificate from the specified file. The certificate file * must be in PEM/Base64 format and start with "BEGIN CERTIFICATE" and end * with "END CERTIFICATE" line. * * @param file the file to load the certificate from. * @return <code>java.security.cert.X509Certificate</code> the loaded * certificate. * @throws IOException if I/O error occurs * @throws GeneralSecurityException if security problems occurs. */ public static X509Certificate loadCertificate(String file) throws IOException, GeneralSecurityException { if (file == null) { throw new IllegalArgumentException("Certificate file is null"); //i18n // .getMessage("certFileNull")); } X509Certificate cert = null; BufferedReader reader = new BufferedReader(new FileReader(file)); try { cert = readCertificate(reader); } finally { reader.close(); } if (cert == null) { throw new GeneralSecurityException("No certificate data"); //i18n.getMessage("noCertData")); } return cert; } /** * Loads multiple X.509 certificates from the specified file. Each * certificate must be in PEM/Base64 format and start with "BEGIN * CERTIFICATE" and end with "END CERTIFICATE" line. * * @param file the certificate file to load the certificate from. * @return an array of certificates loaded from the file. * @throws IOException if I/O error occurs * @throws GeneralSecurityException if security problems occurs. */ public static X509Certificate[] loadCertificates(String file) throws IOException, GeneralSecurityException { if (file == null) { throw new IllegalArgumentException("Certificate file is null"); //i18n // .getMessage("certFileNull")); } List<X509Certificate> list = new ArrayList<X509Certificate>(); BufferedReader reader = new BufferedReader(new FileReader(file)); X509Certificate cert = readCertificate(reader); try { while (cert != null) { list.add(cert); cert = readCertificate(reader); } } finally { reader.close(); } if (list.size() == 0) { throw new GeneralSecurityException("No certificate data"); //i18n.getMessage("noCertData")); } int size = list.size(); return list.toArray(new X509Certificate[size]); } /** * Loads a X.509 certificate from the specified reader. The certificate * contents must start with "BEGIN CERTIFICATE" line and end with "END * CERTIFICATE" line, and be in PEM/Base64 format. * <p/> * This function does not close the input stream. * * @param reader the stream from which load the certificate. * @return the loaded certificate or null if there was no certificate in the * stream or the stream is closed. * @throws IOException if I/O error occurs * @throws GeneralSecurityException if security problems occurs. */ public static X509Certificate readCertificate(BufferedReader reader) throws IOException, GeneralSecurityException { String line; StringBuffer buff = new StringBuffer(); boolean isCert = false; boolean isKey = false; boolean notNull = false; while ((line = reader.readLine()) != null) { // Skip key info, if any if (line.indexOf("BEGIN RSA PRIVATE KEY") != -1 || line.indexOf("BEGIN PRIVATE KEY") != -1) { isKey = true; continue; } else if (isKey && (line.indexOf("END RSA PRIVATE KEY") != -1 || line.indexOf("END PRIVATE KEY") != -1)) { isKey = false; continue; } else if (isKey) continue; notNull = true; if (line.indexOf("BEGIN CERTIFICATE") != -1) { isCert = true; } else if (isCert && line.indexOf("END CERTIFICATE") != -1) { byte[] data = Base64.decode(buff.toString().getBytes()); return loadCertificate(new ByteArrayInputStream(data)); } else if (isCert) { buff.append(line); } } if (notNull && !isCert) { throw new GeneralSecurityException("Certificate needs to start with " + " BEGIN CERTIFICATE"); } return null; } public static X509CRL loadCrl(String file) throws IOException, GeneralSecurityException { if (file == null) { throw new IllegalArgumentException("crlFileNull"); //i18n.getMessage("crlFileNull")); } boolean isCrl = false; X509CRL crl = null; BufferedReader reader; String line; StringBuffer buff = new StringBuffer(); reader = new BufferedReader(new FileReader(file)); try { while ((line = reader.readLine()) != null) { if (line.indexOf("BEGIN X509 CRL") != -1) { isCrl = true; } else if (isCrl && line.indexOf("END X509 CRL") != -1) { byte[] data = Base64.decode(buff.toString().getBytes()); crl = loadCrl(new ByteArrayInputStream(data)); } else if (isCrl) { buff.append(line); } } } finally { reader.close(); } if (crl == null) { throw new GeneralSecurityException("noCrlsData"); //i18n.getMessage("noCrlData")); } return crl; } public static X509CRL loadCrl(InputStream in) throws GeneralSecurityException { return (X509CRL) getCertificateFactory().generateCRL(in); } public static Collection<X509Certificate> getTrustedCertificates(KeyStore keyStore, X509CertSelector selector) throws KeyStoreException { Vector<X509Certificate> certificates = new Vector<X509Certificate>(); Enumeration<String> aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); if (keyStore.isCertificateEntry(alias)) { // If a specific impl of keystore requires refresh, this would be a // good place to add it. Certificate certificate = keyStore.getCertificate(alias); if (certificate instanceof X509Certificate) { X509Certificate x509Cert = (X509Certificate) certificate; if (selector == null) { certificates.add(x509Cert); } else if (selector.match(certificate)) { certificates.add(x509Cert); } } } } return certificates; } }