All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xades4j.providers.impl.PKIXCertificateValidationProvider Maven / Gradle / Ivy

Go to download

The XAdES4j library is an high-level, configurable and extensible Java implementation of XML Advanced Electronic Signatures (XAdES 1.3.2 and 1.4.1). It enables producing, verifying and extending signatures in the main XAdES forms: XAdES-BES, XAdES-EPES, XAdES-T and XAdES-C. Also, extended forms are supported through the enrichment of an existing signature.

There is a newer version: 2.2.2
Show newest version
/*
 * XAdES4j - A Java library for generation and verification of XAdES signatures.
 * Copyright (C) 2010 Luis Goncalves.
 *
 * XAdES4j is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or any later version.
 *
 * XAdES4j 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 Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with XAdES4j. If not, see .
 */
package xades4j.providers.impl;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLSelector;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
import xades4j.providers.CannotBuildCertificationPathException;
import xades4j.providers.CannotSelectCertificateException;
import xades4j.providers.CertificateValidationException;
import xades4j.providers.CertificateValidationProvider;
import xades4j.providers.ValidationData;
import xades4j.verification.UnexpectedJCAException;

/**
 * Implementation of {@code CertificateValidationProvider} using a PKIX {@code CertPathBuilder}.
 * 

* Since the Java's PKIX API doesn't allow to access the CRLs used in the certification * path validation, this is manually done. There has to be a CRL for each issuer * in the path which is valid at the moment of validation (signature and date). * @author Luís */ public class PKIXCertificateValidationProvider implements CertificateValidationProvider { private static final int DEFAULT_MAX_PATH_LENGTH = 6; private final KeyStore trustAnchors; private final boolean revocationEnabled; private final int maxPathLength; private final CertStore[] intermCertsAndCrls; private final CertPathBuilder certPathBuilder; private final String signatureProvider; /** * Initializes a new instance that uses the specified JCE providers for CertPathBuilder * and Signature. * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry}) * @param revocationEnabled whether revocation is enabled * @param maxPathLength the maximum length of the certification paths * @param certPathBuilderProvider the CertPathBuilder provider * @param signatureProvider the Signature provider * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be * used in the construction of the certification path. May contain CRLs to be used * if revocation is enabled * @see xades4j.utils.FileSystemDirectoryCertStore * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder */ public PKIXCertificateValidationProvider( KeyStore trustAnchors, boolean revocationEnabled, int maxPathLength, String certPathBuilderProvider, String signatureProvider, CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException { if (null == trustAnchors) { throw new NullPointerException("Trust anchors cannot be null"); } this.trustAnchors = trustAnchors; this.revocationEnabled = revocationEnabled; this.maxPathLength = maxPathLength; this.certPathBuilder = certPathBuilderProvider == null ? CertPathBuilder.getInstance("PKIX") : CertPathBuilder.getInstance("PKIX", certPathBuilderProvider); this.signatureProvider = signatureProvider; this.intermCertsAndCrls = intermCertsAndCrls; } /** * Initializes a new instance that uses the specified JCE providers for CertPathBuilder * and Signature. * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry}) * @param revocationEnabled whether revocation is enabled * @param certPathBuilderProvider the CertPathBuilder provider * @param signatureProvider the Signature provider * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be * used in the construction of the certification path. May contain CRLs to be used * if revocation is enabled * @see xades4j.utils.FileSystemDirectoryCertStore * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder */ public PKIXCertificateValidationProvider( KeyStore trustAnchors, boolean revocationEnabled, String certPathBuilderProvider, String signatureProvider, CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException { this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, certPathBuilderProvider, signatureProvider, intermCertsAndCrls); } /** * Initializes a new instance that uses the specified JCE provider for both * CertPathBuilder and Signature. * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry}) * @param revocationEnabled whether revocation is enabled * @param maxPathLength the maximum length of the certification paths * @param jceProvider the CertPathBuilder and Signature provider * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be * used in the construction of the certification path. May contain CRLs to be used * if revocation is enabled * @see xades4j.utils.FileSystemDirectoryCertStore * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder */ public PKIXCertificateValidationProvider( KeyStore trustAnchors, boolean revocationEnabled, int maxPathLength, String jceProvider, CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException { this(trustAnchors, revocationEnabled, maxPathLength, jceProvider, jceProvider, intermCertsAndCrls); } /** * Initializes a new instance that uses the specified JCE provider for both * CertPathBuilder and Signature. * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry}) * @param revocationEnabled whether revocation is enabled * @param jceProvider the CertPathBuilder and Signature provider * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be * used in the construction of the certification path. May contain CRLs to be used * if revocation is enabled * @see xades4j.utils.FileSystemDirectoryCertStore * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder */ public PKIXCertificateValidationProvider( KeyStore trustAnchors, boolean revocationEnabled, String jceProvider, CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException { this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, jceProvider, intermCertsAndCrls); } /** * Initializes a new instance without specifying the JCE providers for CertPathBuilder * and Signature. * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry}) * @param revocationEnabled whether revocation is enabled * @param maxPathLength the maximum length of the certification paths * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be * used in the construction of the certification path. May contain CRLs to be used * if revocation is enabled * @see xades4j.utils.FileSystemDirectoryCertStore * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder */ public PKIXCertificateValidationProvider( KeyStore trustAnchors, boolean revocationEnabled, int maxPathLength, CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException { this(trustAnchors, revocationEnabled, maxPathLength, null, null, intermCertsAndCrls); } /** * Initializes a new instance without specifying the JCE providers for CertPathBuilder * and Signature. * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry}) * @param revocationEnabled whether revocation is enabled * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be * used in the construction of the certification path. May contain CRLs to be used * if revocation is enabled * @see xades4j.utils.FileSystemDirectoryCertStore * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder */ public PKIXCertificateValidationProvider( KeyStore trustAnchors, boolean revocationEnabled, CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException { this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, null, null, intermCertsAndCrls); } @Override public ValidationData validate( X509CertSelector certSelector, Date validationDate, Collection otherCerts) throws CertificateValidationException, UnexpectedJCAException { PKIXBuilderParameters builderParams; try { builderParams = new PKIXBuilderParameters(trustAnchors, certSelector); } catch (KeyStoreException ex) { throw new CannotBuildCertificationPathException(certSelector, "Trust anchors KeyStore is not initialized", ex); } catch (InvalidAlgorithmParameterException ex) { throw new CannotBuildCertificationPathException(certSelector, "Trust anchors KeyStore has no trusted certificate entries", ex); } PKIXCertPathBuilderResult builderRes; try { // Certificates to be used to build the certification path. // - The other certificates from the signature (e.g. from KeyInfo). if (otherCerts != null) { CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(otherCerts); CertStore othersCertStore = CertStore.getInstance("Collection", ccsp); builderParams.addCertStore(othersCertStore); } // - The external certificates/CRLs. for (int i = 0; i < intermCertsAndCrls.length; i++) { builderParams.addCertStore(intermCertsAndCrls[i]); } builderParams.setRevocationEnabled(revocationEnabled); builderParams.setMaxPathLength(maxPathLength); builderParams.setDate(validationDate); builderParams.setSigProvider(this.signatureProvider); builderRes = (PKIXCertPathBuilderResult) certPathBuilder.build(builderParams); } catch (CertPathBuilderException ex) { throw new CannotBuildCertificationPathException(certSelector, ex.getMessage(), ex); } catch (InvalidAlgorithmParameterException ex) { // SHOULD NOT be thrown due to wrong type of parameters. // Seems to be thrown when the CertSelector (in builderParams) criteria // cannot be applied. throw new CannotSelectCertificateException(certSelector, ex); } catch (NoSuchAlgorithmException ex) { // SHOULD NOT be thrown. throw new UnexpectedJCAException("No provider for Collection CertStore", ex); } // The cert path returned by the builder ends in a certificate issued by // the trust anchor. However, the complete path may be needed for property // verification. List certPath = (List) builderRes.getCertPath().getCertificates(); // - Create a new list since the previous is immutable. certPath = new ArrayList(certPath); // - Add the trust anchor certificate. certPath.add(builderRes.getTrustAnchor().getTrustedCert()); if (revocationEnabled) { return new ValidationData(certPath, getCRLsForCertPath(certPath, validationDate)); } return new ValidationData(certPath); } private Collection getCRLsForCertPath( List certPath, Date validationDate) throws CertificateValidationException { // Map the issuers certificates in the chain. This is used to know the issuers // and later to verify the signatures in the CRLs. Map issuersCerts = new HashMap(certPath.size() - 1); for (int i = 0; i < certPath.size() - 1; i++) { // The issuer of one certificate is the subject of the following one. issuersCerts.put(certPath.get(i).getIssuerX500Principal(), certPath.get(i + 1)); } // Select all the CRLs from the issuers involved in the certification path // that are valid at the moment. X509CRLSelector crlSelector = new X509CRLSelector(); for (X500Principal issuer : issuersCerts.keySet()) { // - "The issuer distinguished name in the X509CRL must match at least // one of the specified distinguished names." crlSelector.addIssuer(issuer); } // - "The specified date must be equal to or later than the value of the // thisUpdate component of the X509CRL and earlier than the value of the // nextUpdate component." crlSelector.setDateAndTime(validationDate); Set crls = new HashSet(); try { // Get the CRLs on each CertStore. for (int i = 0; i < intermCertsAndCrls.length; i++) { Collection storeCRLs = intermCertsAndCrls[i].getCRLs(crlSelector); crls.addAll(Collections.checkedCollection(storeCRLs, X509CRL.class)); } } catch (CertStoreException ex) { throw new CertificateValidationException(null, "Cannot get CRLs", ex); } // Verify the CRLs' signatures. The issuers' certificates were validated // as part of the cert path creation. for (X509CRL crl : crls) { try { X509Certificate crlIssuerCert = issuersCerts.get(crl.getIssuerX500Principal()); if (null == this.signatureProvider) { crl.verify(crlIssuerCert.getPublicKey()); } else { crl.verify(crlIssuerCert.getPublicKey(), this.signatureProvider); } } catch (Exception ex) { throw new CertificateValidationException(null, "Invalid CRL signature from " + crl.getIssuerX500Principal().getName(), ex); } } return crls; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy