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

org.bouncycastle.cert.test.CertPathLoopTest Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. This jar contains APIs for JDK 1.5 and up. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.

The newest version!
package org.bouncycastle.cert.test;

import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathBuilderResult;
import java.security.cert.CertStore;
import java.security.cert.CertStoreParameters;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.TrustAnchor;
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.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v2CRLBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.util.test.SimpleTest;


/**
 * BC bug test case.
 */
public class CertPathLoopTest
    extends SimpleTest
{
    /**
     * List of trust anchors
     */
    private static Set taSet;
    /**
     * List of certificates and CRLs
     */
    private static List otherList;

    /**
     * Asks the user about the configuration he want's to test
     *
     * @param caA
     * @param caB
     */
    private static void checkUseDistinctCAs(CA caA, CA caB)
    {
        //Standard configuration : everything in caA
        taSet = new HashSet();
        taSet.add(caA.ta);
        otherList = new ArrayList();
        otherList.add(caA.acCertCrl);
        otherList.add(caA.crl);
        //User specified configuration : parts of caB

        taSet.add(caB.ta);
        otherList.add(caB.acCertCrl);
        otherList.add(caB.crl);
    }

    /**
     * Creates a collection cert store
     */
    static CertStore getStore(Collection col)
        throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
    {
        CertStoreParameters csp = new CollectionCertStoreParameters(col);
        return CertStore.getInstance("Collection", csp);
    }

    public String getName()
    {
        return "CertPath Loop Test";
    }

    public void performTest()
        throws Exception
    {
              //Add the provider
        Security.addProvider(new BouncyCastleProvider());
        //Generate two Cert authorities
        CA caA = new CA();
        CA caB = new CA();
        //Ask the user the conf he want's to test
        checkUseDistinctCAs(caA, caB);

        //Let's create a target cert under caA
        X509CertSelector target = new X509CertSelector();
        target.setCertificate(caA.makeNewCert());
        //create control parameters
        PKIXBuilderParameters params = new PKIXBuilderParameters(taSet, target);
        params.addCertStore(getStore(Collections.singleton(target.getCertificate())));
        params.addCertStore(getStore(otherList));
        //enable revocation check
        params.setRevocationEnabled(true);

        //Lets Build the path
        try
        {
            CertPathBuilderResult cpbr = CertPathBuilder.getInstance("PKIX", "BC").build(params);

            fail("invalid path build");
        }
        catch (CertPathBuilderException e)
        {
            if (!e.getCause().getMessage().equals("CertPath for CRL signer failed to validate."))
            {
                fail("Exception thrown, but wrong one", e.getCause());
            }
        }
    }

    /**
     * Class simulating a certification authority
     */
    private static class CA
    {
        /**
         * key pair generator
         */
        final static KeyPairGenerator kpg;

        static
        {
            try
            {
                kpg = KeyPairGenerator.getInstance("RSA");
                //Key size doesn't matter, smaller == Faster
                kpg.initialize(512);
            }
            catch (NoSuchAlgorithmException e)
            {
                throw new RuntimeException(e);
            }
        }

        /**
         * KeyPair signing certificates
         */
        private KeyPair caCertKp;
        /**
         * KeyPair signing CRLs
         */
        private KeyPair caCrlKp;
        TrustAnchor ta;
        /**
         * Subject of this CA
         */
        X500Name acSubject;
        /**
         * Certificate signing certificates
         */
        X509Certificate acCertAc;
        /**
         * Certificate signing CRLs
         */
        X509Certificate acCertCrl;
        /**
         * the CRL
         */
        X509CRL crl;
        /**
         * Signers
         */
        private ContentSigner caCrlSigner, caCertSigner;
        /**
         * Serial number counter
         */
        private int counter = 1;

        /**
         * Constructor
         */
        public CA()
            throws Exception
        {
            //Init both keypairs
            caCertKp = kpg.generateKeyPair();
            caCrlKp = kpg.generateKeyPair();
            //subject
            acSubject = new X500Name("CN=AC_0");
            //validity
            GregorianCalendar gc = new GregorianCalendar();
            Date notBefore = gc.getTime();
            gc.add(GregorianCalendar.DAY_OF_YEAR, 1);
            Date notAfter = gc.getTime();
            //first signer
            caCertSigner = new JcaContentSignerBuilder("SHA1withRSA").build(caCertKp.getPrivate());
            //top level : issuer is self
            X500Name issuer = acSubject;
            //reserved for future use (another test case)
            ContentSigner thisAcSigner = caCertSigner;
            //reserved for future use (another test case)
            //First certificate: Certificate authority (BasicConstraints=true) but not CRLSigner
            X509CertificateHolder certH = new X509v3CertificateBuilder(
                issuer, BigInteger.valueOf(counter++), notBefore, notAfter, acSubject, getPublicKeyInfo(caCertKp.getPublic()))
                .addExtension(Extension.basicConstraints, true, new BasicConstraints(true))
                .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign))
                .build(thisAcSigner);
            //lets convert to X509Certificate
            acCertAc = convert(certH);
            //and build a trust Anchor
            ta = new TrustAnchor(acCertAc, null);

            //Second signer
            caCrlSigner = new JcaContentSignerBuilder("SHA1withRSA").build(caCrlKp.getPrivate());
            //second certificate: CRLSigner but not Certificate authority (BasicConstraints=false)
            certH = new X509v3CertificateBuilder(
                issuer, BigInteger.valueOf(counter++), notBefore, notAfter, acSubject, getPublicKeyInfo(caCrlKp.getPublic()))
                .addExtension(Extension.basicConstraints, false, new BasicConstraints(false))
                .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.cRLSign))
                .build(thisAcSigner);
            //lets convert to X509Certificate
            acCertCrl = convert(certH);
            //And create the CRL
            X509CRLHolder crlH = new X509v2CRLBuilder(acSubject, notBefore).setNextUpdate(notAfter).build(caCrlSigner);
            //lets convert to X509CRL
            crl = convert(crlH);
        }

        /**
         * Creates a child certificate
         */
        public X509Certificate makeNewCert()
            throws Exception
        {
            //private key doesn't matter for the test
            PublicKey publicKey = kpg.generateKeyPair().getPublic();
            //Validity
            GregorianCalendar gc = new GregorianCalendar();
            Date notBefore = gc.getTime();
            gc.add(GregorianCalendar.DAY_OF_YEAR, 1);
            Date notAfter = gc.getTime();
            //serial
            BigInteger certSerial = BigInteger.valueOf(counter++);
            //Distinct name based on the serial
            X500Name subject = new X500Name("CN=EU_" + certSerial.toString());
            //End user certificate, not allowed to do anything
            X509CertificateHolder enUserCertH = new X509v3CertificateBuilder(
                acSubject, certSerial, notBefore, notAfter, subject, getPublicKeyInfo(publicKey))
                .addExtension(Extension.basicConstraints, false, new BasicConstraints(false))
                .addExtension(Extension.keyUsage, true, new KeyUsage(0))
                .build(caCertSigner);

            //lets convert to X509Certificate
            return convert(enUserCertH);
        }


        /**
         * convert to X509Certificate
         */
        static X509Certificate convert(X509CertificateHolder h)
            throws Exception
        {
            return new JcaX509CertificateConverter().getCertificate(h);
        }

        /**
         * convert to X509CRL
         */
        static X509CRL convert(X509CRLHolder h)
            throws Exception
        {
            return new JcaX509CRLConverter().getCRL(h);
        }

        /**
         * convert to SubjectPublicKeyInfo
         */
        static SubjectPublicKeyInfo getPublicKeyInfo(PublicKey k)
            throws Exception
        {
            return SubjectPublicKeyInfo.getInstance(k.getEncoded());
        }
    }

    public static void main(String[] args)
    {
        runTest(new CertPathLoopTest());
    }
}