Java tutorial
/* * Copyright (c) 2008-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.security.crl; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; import java.security.NoSuchProviderException; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import mitm.common.security.SecurityFactoryFactory; import mitm.common.security.SecurityFactoryFactoryException; import mitm.common.security.asn1.ObjectEncoding; import mitm.common.util.MissingDateException; import mitm.common.util.URIUtils; import org.apache.commons.io.IOUtils; import org.bouncycastle.asn1.x509.CRLDistPoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CRLUtils { private final static Logger logger = LoggerFactory.getLogger(CRLUtils.class); /** * Reads and returns all encoded CRLs from the input stream. */ public static Collection<? extends CRL> readCRLs(InputStream input) throws CertificateException, NoSuchProviderException, SecurityFactoryFactoryException, CRLException { if (!(input instanceof BufferedInputStream)) { input = new BufferedInputStream(input); } CertificateFactory fac = SecurityFactoryFactory.getSecurityFactory().createCertificateFactory("X.509"); return fac.generateCRLs(input); } /** * Reads and returns all encoded X509CRLs from the input stream. */ public static Collection<X509CRL> readX509CRLs(InputStream input) throws CertificateException, NoSuchProviderException, SecurityFactoryFactoryException, CRLException { Collection<? extends CRL> crls = readCRLs(input); List<X509CRL> x509CRLs = new LinkedList<X509CRL>(); for (CRL crl : crls) { if (crl instanceof X509CRL) { x509CRLs.add((X509CRL) crl); } } return x509CRLs; } /** * Reads and returns all encoded X509CRLs from the file. */ public static Collection<? extends CRL> readCRLs(File file) throws CertificateException, NoSuchProviderException, SecurityFactoryFactoryException, CRLException, FileNotFoundException { FileInputStream input = new FileInputStream(file); BufferedInputStream buffered = new BufferedInputStream(input); try { return readCRLs(buffered); } finally { IOUtils.closeQuietly(buffered); IOUtils.closeQuietly(input); } } /** * Writes all X509 CRLs to the output stream encoded with the given encoding */ public static void writeX509CRLs(Collection<X509CRL> crls, OutputStream output, ObjectEncoding encoding) throws CertificateEncodingException, CRLException, IOException { byte[] encoded = CRLEncoder.encode(crls, encoding); output.write(encoded); } /** * Returns all the CRL distribution point URLs from the provided distPoint extension. */ public static Set<URI> getAllDistributionPointURIs(CRLDistPoint distPoint) throws CRLException { Set<URI> uris = new HashSet<URI>(); if (distPoint == null) { return uris; } Set<String> names = CRLDistributionPointsInspector.getURIDistributionPointNames(distPoint); for (String name : names) { try { /* * Encode the input when the URI is not valid because some certificates contain * incorrectly encoded URL's. */ URI uri = URIUtils.toURI(name, true /* encode */); if (uri != null) { uris.add(uri); } } catch (URISyntaxException e) { logger.warn("Could not create URI from '" + name + "'. Reason: " + e.getMessage()); } } return uris; } /** * Returns true if the crl is newer than the other crl. A crl can have a CRL number which must be a * positive integer. If a crl is newer the crl number should be higher. If the CRL does not have * a CRL number we will compare the thisUpdate (CRL issuing date). */ public static boolean isNewer(X509CRL crl, X509CRL otherCRL) throws IOException, MissingDateException { return compare(crl, otherCRL) > 0; } /** * Returns 0 if crl and otherCRL have similar validity (ie no one is newer than the other), * > 0 if crl is newer than otherCRL and < 0 if crl is older than otherCRL */ public static int compare(X509CRL crl, X509CRL otherCRL) throws IOException, MissingDateException { BigInteger crlNumber = X509CRLInspector.getCRLNumber(crl); BigInteger otherCRLNumber = X509CRLInspector.getCRLNumber(crl); Date thisUpdate = crl.getThisUpdate(); Date otherThisUpdate = otherCRL.getThisUpdate(); if (thisUpdate == null || otherThisUpdate == null) { throw new MissingDateException("One of the CRLs has a missing thisUpdate."); } int cmp; if (crlNumber != null && otherCRLNumber != null) { cmp = crlNumber.compareTo(otherCRLNumber); if (cmp > 0) { if (thisUpdate.before(otherThisUpdate)) { logger.warn("According to CRL numbers a new CRL is found but thisUpdate is older."); } logger.debug("The CRL number is bigger and is therefore more recent."); } else if (cmp == 0) { /* * same CRL number but thisUpdate can be newer */ cmp = thisUpdate.compareTo(otherThisUpdate); if (cmp > 0) { logger.debug("The CRL numbers are equal but thisUpdate is newer."); } } else { if (thisUpdate.after(otherThisUpdate)) { logger.warn("According to CRL numbers this not a new CRL but thisUpdate is newer."); } } } else { /* * no CRL number so compare thisUpdate */ cmp = thisUpdate.compareTo(otherThisUpdate); if (cmp > 0) { logger.debug("A more recent CRL is found."); } } return cmp; } }