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

eu.europa.esig.dss.spi.x509.CertificateReorderer Maven / Gradle / Ivy

/**
 * DSS - Digital Signature Services
 * Copyright (C) 2015 European Commission, provided under the CEF programme
 * 

* This file is part of the "DSS - Digital Signature Services" project. *

* This library 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 2.1 of the License, or (at your option) any later version. *

* This library 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package eu.europa.esig.dss.spi.x509; import eu.europa.esig.dss.model.DSSException; import eu.europa.esig.dss.model.x509.CertificateToken; import eu.europa.esig.dss.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.PublicKey; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Reorders a certificate collection to the corresponding certificate chain */ public class CertificateReorderer { private static final Logger LOG = LoggerFactory.getLogger(CertificateReorderer.class); /** The signing certificate (the last certificate in the chain) */ private final CertificateToken signingCertificate; /** The collection of certificates */ private final Collection certificateChain; /** * Constructor which takes a collection of certificates where DSS needs to find * the signing certificate * * @param certificateChain * a collection of {@link CertificateToken}s */ public CertificateReorderer(Collection certificateChain) { this(null, certificateChain); } /** * Constructor which takes a potential signing certificate and a certificate chain * * @param signingCertificate * {@link CertificateToken} the potential signing certificate * @param certificateChain * a collection of {@link CertificateToken}s */ public CertificateReorderer(CertificateToken signingCertificate, Collection certificateChain) { this.signingCertificate = signingCertificate; this.certificateChain = certificateChain; } /** * This method is used to order the certificates (signing certificate, CA1, CA2 and Root) * * @return a list of ordered {@link CertificateToken}s */ public List getOrderedCertificates() { List certificates = getAllCertificatesOnce(); if (Utils.collectionSize(certificates) == 1) { return certificates; } initIssuerPublicKeys(certificates); // Build complete chain List identifiedSigningCerts = getSigningCertificates(certificates); CertificateToken selectedSigningCert = selectSigningCertificateInList(identifiedSigningCerts); List rebuiltCertificateChain = buildCertificateChainForCert(certificates, selectedSigningCert); if (certificates.size() > rebuiltCertificateChain.size()) { LOG.debug("Some certificates are ignored"); LOG.debug("Before : {}", certificates); LOG.debug("After : {}", rebuiltCertificateChain); } return rebuiltCertificateChain; } /** * This method is used to order the certificates (signing certificate, CA1, CA2 * and Root) * * @return a map of one or more ordered certificates chain */ public Map> getOrderedCertificateChains() { Map> result = new HashMap<>(); List certificates = getAllCertificatesOnce(); if (Utils.collectionSize(certificates) == 1) { CertificateToken uniqueCert = certificates.get(0); result.put(uniqueCert, Collections.singletonList(uniqueCert)); return result; } initIssuerPublicKeys(certificates); List identifiedSigningCerts = getSigningCertificates(certificates); for (CertificateToken identifiedSigningCert : identifiedSigningCerts) { result.put(identifiedSigningCert, buildCertificateChainForCert(certificates, identifiedSigningCert)); } return result; } private void initIssuerPublicKeys(List certificates) { // Build the chain cert -> issuer for (CertificateToken token : certificates) { if (isIssuerNeeded(token)) { for (CertificateToken signer : certificates) { if (token.isSignedBy(signer)) { LOG.debug("{} is signed by {}", token.getDSSIdAsString(), signer.getDSSIdAsString()); break; } } if (isIssuerNeeded(token)) { LOG.warn("Issuer not found for certificate {}", token.getDSSIdAsString()); } } } } private List buildCertificateChainForCert(List certificates, CertificateToken certToAdd) { List result = new LinkedList<>(); while (certToAdd != null && !result.contains(certToAdd)) { result.add(certToAdd); certToAdd = getCertificateByPubKey(certificates, certToAdd.getPublicKeyOfTheSigner()); } return result; } private CertificateToken getCertificateByPubKey(List certificates, PublicKey publicKeyOfTheSigner) { for (CertificateToken certificateToken : certificates) { if (certificateToken.getPublicKey().equals(publicKeyOfTheSigner)) { return certificateToken; } } return null; } private boolean isIssuerNeeded(CertificateToken token) { return !token.isSelfSigned() && token.getPublicKeyOfTheSigner() == null; } private CertificateToken selectSigningCertificateInList(List identifiedSigningCerts) { CertificateToken selectedSigningCert; if (identifiedSigningCerts.size() == 1) { selectedSigningCert = identifiedSigningCerts.get(0); } else { LOG.warn("More than one chain detected"); if (signingCertificate != null && identifiedSigningCerts.contains(signingCertificate)) { selectedSigningCert = signingCertificate; } else { throw new DSSException("Unable to determine a signing certificate : No pertinent input parameters"); } } return selectedSigningCert; } /** * This method is used to avoid duplicate entries * * @return a list with all certificates */ private List getAllCertificatesOnce() { List result = new ArrayList<>(); if (signingCertificate != null) { result.add(signingCertificate); } if (Utils.isCollectionNotEmpty(certificateChain)) { for (CertificateToken certificateToken : certificateChain) { if (certificateToken != null && !result.contains(certificateToken)) { result.add(certificateToken); } } } return result; } /** * This method is used to identify the signing certificates (the certificate * which didn't sign any other certificate) * * @param certificates a collection of {@link CertificateToken}s * @return the identified signing certificates */ private List getSigningCertificates(List certificates) { if (Utils.isCollectionEmpty(certificates)) { throw new DSSException("No signing certificate found"); } List potentialSigners = new ArrayList<>(); for (CertificateToken signer : certificates) { boolean caCert = false; for (CertificateToken token : certificates) { if (signer.getPublicKey().equals(token.getPublicKeyOfTheSigner())) { caCert = true; break; } } if (!caCert) { potentialSigners.add(signer); } } if (Utils.isCollectionEmpty(potentialSigners)) { throw new DSSException("The certificate chain contains only bridge certificates"); } return potentialSigners; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy