be.fedict.trust.BelgianTrustValidatorFactory.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.trust.BelgianTrustValidatorFactory.java

Source

/*
 * Java Trust Project.
 * Copyright (C) 2009 FedICT.
 * Copyright (C) 2013-2014 e-Contract.be BVBA.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software 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 software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.trust;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

import be.fedict.trust.constraints.CertificatePoliciesCertificateConstraint;
import be.fedict.trust.constraints.DistinguishedNameCertificateConstraint;
import be.fedict.trust.constraints.KeyUsageCertificateConstraint;
import be.fedict.trust.constraints.QCStatementsCertificateConstraint;
import be.fedict.trust.constraints.TSACertificateConstraint;
import be.fedict.trust.crl.CrlRepository;
import be.fedict.trust.linker.TrustLinker;
import be.fedict.trust.repository.CertificateRepository;
import be.fedict.trust.repository.MemoryCertificateRepository;

/**
 * Trust Validator Factory for Belgian (eID) PKI.
 * 
 * @author Frank Cornelis
 * 
 */
public class BelgianTrustValidatorFactory {

    private static final Log LOG = LogFactory.getLog(BelgianTrustValidatorFactory.class);

    /**
     * Creates a trust validator according to Belgian PKI rules for
     * authentication certificates.
     * 
     * @return a trust validator instance.
     */
    public static TrustValidator createTrustValidator() {
        return createTrustValidator(null);
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for
     * authentication certificates.
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createTrustValidator(NetworkConfig networkConfig) {
        TrustValidator trustValidator = createTrustValidator(networkConfig, null);
        return trustValidator;
    }

    private enum CertificateType {
        AUTHN, SIGN, NATIONAL_REGISTRY
    };

    /**
     * Creates a trust validator according to Belgian PKI rules for
     * authentication certificates.
     * 
     * <p>
     * Via the external trust linker one can implement a CRL fetcher validation
     * architecture based on Java EE.
     * </p>
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @param externalTrustLinker
     *            the optional external trust linker to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createTrustValidator(NetworkConfig networkConfig,
            TrustLinker externalTrustLinker) {
        TrustValidator trustValidator = createTrustValidator(CertificateType.AUTHN, networkConfig,
                externalTrustLinker, null, null);

        return trustValidator;
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for
     * non-repudiation certificates.
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @param externalTrustLinker
     *            the optional external trust linker to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createNonRepudiationTrustValidator(NetworkConfig networkConfig,
            TrustLinker externalTrustLinker) {
        TrustValidator trustValidator = createTrustValidator(CertificateType.SIGN, networkConfig,
                externalTrustLinker, null, null);

        return trustValidator;
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for
     * non-repudiation certificates.
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createNonRepudiationTrustValidator(NetworkConfig networkConfig) {
        TrustValidator trustValidator = createTrustValidator(CertificateType.SIGN, networkConfig, null, null, null);

        return trustValidator;
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for the national
     * registry certificate.
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createNationalRegistryTrustValidator(NetworkConfig networkConfig) {
        TrustValidator trustValidator = createTrustValidator(CertificateType.NATIONAL_REGISTRY, networkConfig, null,
                null, null);

        return trustValidator;
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for TSA
     * certificates.
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createTSATrustValidator(NetworkConfig networkConfig) {
        return createTSATrustValidator(networkConfig, null);
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for TSA
     * certificates.
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @param externalTrustLinker
     *            the optional external trust linker to be used.
     * @return a trust validator instance.
     */
    public static TrustValidator createTSATrustValidator(NetworkConfig networkConfig,
            TrustLinker externalTrustLinker) {

        CertificateRepository certificateRepository = createTSACertificateRepository();

        TrustValidator trustValidator = new TrustValidator(certificateRepository);

        // add trust linkers
        TrustValidatorDecorator trustValidatorDecorator = new TrustValidatorDecorator(networkConfig);
        trustValidatorDecorator.addDefaultTrustLinkerConfig(trustValidator, externalTrustLinker);

        // add certificate constraints
        trustValidator.addCertificateConstrain(new TSACertificateConstraint());

        return trustValidator;
    }

    /**
     * Creates a trust validator according to Belgian PKI rules for
     * authentication certificates.
     * 
     * <p>
     * Via the external trust linker one can implement a CRL fetcher validation
     * architecture based on Java EE.
     * </p>
     * 
     * @param networkConfig
     *            the optional network configuration to be used.
     * @param externalTrustLinker
     *            the optional external trust linker to be used.
     * @param certificateRepository
     *            containing the Belgian eID trust points.
     * @return a trust validator instance.
     */
    public static TrustValidator createTrustValidator(NetworkConfig networkConfig, TrustLinker externalTrustLinker,
            CertificateRepository certificateRepository) {
        return createTrustValidator(CertificateType.AUTHN, networkConfig, externalTrustLinker,
                certificateRepository, null);
    }

    public static CertificateRepository createCertificateRepository() {
        MemoryCertificateRepository memoryCertificateRepository = new MemoryCertificateRepository();

        X509Certificate rootCaCertificate = loadCertificate("be/fedict/trust/belgiumrca.crt");
        memoryCertificateRepository.addTrustPoint(rootCaCertificate);

        X509Certificate rootCa2Certificate = loadCertificate("be/fedict/trust/belgiumrca2.crt");
        memoryCertificateRepository.addTrustPoint(rootCa2Certificate);

        X509Certificate rootCa3Certificate = loadCertificate("be/fedict/trust/belgiumrca3.crt");
        memoryCertificateRepository.addTrustPoint(rootCa3Certificate);

        X509Certificate rootCa4Certificate = loadCertificate("be/fedict/trust/belgiumrca4.crt");
        memoryCertificateRepository.addTrustPoint(rootCa4Certificate);

        return memoryCertificateRepository;
    }

    public static CertificateRepository createTSACertificateRepository() {
        MemoryCertificateRepository memoryCertificateRepository = new MemoryCertificateRepository();

        X509Certificate rootTsaCertificate = loadCertificate("be/fedict/trust/belgiumtsa.crt");
        memoryCertificateRepository.addTrustPoint(rootTsaCertificate);

        X509Certificate newRootTsaCertificate = loadPemCertificate(
                "be/fedict/trust/roots/Baltimore Cybertrust Root.pem");
        memoryCertificateRepository.addTrustPoint(newRootTsaCertificate);

        return memoryCertificateRepository;
    }

    private static TrustValidator createTrustValidator(CertificateType certificateType, NetworkConfig networkConfig,
            TrustLinker externalTrustLinker, CertificateRepository certificateRepository,
            CrlRepository crlRepository) {

        TrustValidator trustValidator;
        if (null == certificateRepository) {
            // trust points
            CertificateRepository localCertificateRepository = createCertificateRepository();
            trustValidator = new TrustValidator(localCertificateRepository);
        } else {
            trustValidator = new TrustValidator(certificateRepository);
        }

        TrustValidatorDecorator trustValidatorDecorator = new TrustValidatorDecorator(networkConfig);
        trustValidatorDecorator.addDefaultTrustLinkerConfig(trustValidator, externalTrustLinker, false,
                crlRepository);

        KeyUsageCertificateConstraint keyUsageCertificateConstraint = new KeyUsageCertificateConstraint();
        switch (certificateType) {
        case AUTHN:
            keyUsageCertificateConstraint.setDigitalSignatureFilter(true);
            keyUsageCertificateConstraint.setNonRepudiationFilter(false);
            break;
        case SIGN:
            keyUsageCertificateConstraint.setDigitalSignatureFilter(false);
            keyUsageCertificateConstraint.setNonRepudiationFilter(true);
            break;
        case NATIONAL_REGISTRY:
            keyUsageCertificateConstraint.setDigitalSignatureFilter(true);
            keyUsageCertificateConstraint.setNonRepudiationFilter(true);
            break;
        }
        trustValidator.addCertificateConstrain(keyUsageCertificateConstraint);

        CertificatePoliciesCertificateConstraint certificatePoliciesCertificateConstraint = new CertificatePoliciesCertificateConstraint();
        switch (certificateType) {
        case AUTHN:
            // RootCA citizen authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.1.1.1.2.2");
            // RootCA foreigner authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.1.1.1.7.2");
            // RootCA2 citizen authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.9.1.1.2.2");
            // RootCA2 foreigner authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.9.1.1.7.2");
            // RootCA3 citizen authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.10.1.1.2.2");
            // RootCA3 foreigner authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.10.1.1.7.2");
            // RootCA4 citizen authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.12.1.1.2.2");
            // RootCA4 foreigner authn
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.12.1.1.7.2");
            break;
        case SIGN:
            // RootCA citizen sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.1.1.1.2.1");
            // RootCA foreigner sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.1.1.1.7.1");
            // RootCA2 citizen sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.9.1.1.2.1");
            // RootCA2 foreigner sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.9.1.1.7.1");
            // RootCA3 citizen sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.10.1.1.2.1");
            // RootCA3 foreigner sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.10.1.1.7.1");
            // RootCA4 citizen sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.12.1.1.2.1");
            // RootCA4 foreigner sign
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.12.1.1.7.1");
            break;
        case NATIONAL_REGISTRY:
            // Root CA
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.1.1.1.4");
            // Root CA 2
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.9.1.1.4");
            // Root CA 3
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.10.1.1.4");
            // Root CA 4
            certificatePoliciesCertificateConstraint.addCertificatePolicy("2.16.56.12.1.1.4");
            break;
        }
        trustValidator.addCertificateConstrain(certificatePoliciesCertificateConstraint);

        if (CertificateType.NATIONAL_REGISTRY == certificateType) {
            DistinguishedNameCertificateConstraint nameConstraint = new DistinguishedNameCertificateConstraint(
                    "CN=RRN, O=RRN, C=BE");
            trustValidator.addCertificateConstrain(nameConstraint);
        }

        if (CertificateType.SIGN == certificateType) {
            QCStatementsCertificateConstraint qcStatementsCertificateConstraint = new QCStatementsCertificateConstraint(
                    true);
            trustValidator.addCertificateConstrain(qcStatementsCertificateConstraint);
        }

        return trustValidator;
    }

    private static X509Certificate loadPemCertificate(String pemResourceName) {
        CertificateFactory certificateFactory;
        try {
            certificateFactory = CertificateFactory.getInstance("X.509");
        } catch (CertificateException e) {
            throw new RuntimeException("X.509 factory error: " + e.getMessage(), e);
        }
        Thread currentThread = Thread.currentThread();
        ClassLoader classLoader = currentThread.getContextClassLoader();
        InputStream certificateInputStream = classLoader.getResourceAsStream(pemResourceName);
        if (null == certificateInputStream) {
            throw new IllegalArgumentException("resource not found: " + pemResourceName);
        }
        PemReader pemReader = new PemReader(new InputStreamReader(certificateInputStream));
        try {
            try {
                PemObject pemObject;
                pemObject = pemReader.readPemObject();
                X509Certificate certificate = (X509Certificate) certificateFactory
                        .generateCertificate(new ByteArrayInputStream(pemObject.getContent()));
                return certificate;
            } finally {
                pemReader.close();
            }
        } catch (IOException e) {
            throw new RuntimeException("IO error: " + e.getMessage(), e);
        } catch (CertificateException e) {
            throw new RuntimeException("cert error: " + e.getMessage(), e);
        }
    }

    private static X509Certificate loadCertificate(String resourceName) {
        LOG.debug("loading certificate: " + resourceName);
        Thread currentThread = Thread.currentThread();
        ClassLoader classLoader = currentThread.getContextClassLoader();
        InputStream certificateInputStream = classLoader.getResourceAsStream(resourceName);
        if (null == certificateInputStream) {
            throw new IllegalArgumentException("resource not found: " + resourceName);
        }
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) certificateFactory
                    .generateCertificate(certificateInputStream);
            return certificate;
        } catch (CertificateException e) {
            throw new RuntimeException("X509 error: " + e.getMessage(), e);
        }
    }
}