org.cryptable.pki.communication.PKICMPMessages.java Source code

Java tutorial

Introduction

Here is the source code for org.cryptable.pki.communication.PKICMPMessages.java

Source

/**
 * The MIT License (MIT)
 *
 * Copyright (c) <2013> <Cryptable>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */
package org.cryptable.pki.communication;

import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.cmp.*;
import org.bouncycastle.asn1.crmf.*;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.cmp.*;
import org.bouncycastle.cert.crmf.CRMFException;
import org.bouncycastle.cert.crmf.EncryptedValueParser;
import org.bouncycastle.cert.crmf.jcajce.JcaCertificateRequestMessageBuilder;
import org.bouncycastle.cert.crmf.jcajce.JcaPKIArchiveControlBuilder;
import org.bouncycastle.cert.crmf.jcajce.JceAsymmetricValueDecryptorGenerator;
import org.bouncycastle.cert.jcajce.JcaX500NameUtil;
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cms.*;
import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.operator.InputDecryptor;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.io.Streams;
import org.cryptable.pki.model.CertificationResult;
import org.cryptable.pki.model.RevocationInput;
import org.cryptable.pki.util.PKIKeyStore;
import org.cryptable.pki.util.PKIKeyStoreException;

import javax.security.auth.x500.X500Principal;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.text.ParseException;
import java.util.*;

/**
 * The messages class to communicate with the PKI system
 * User: davidtillemans
 * Date: 1/06/13
 * Time: 12:33
 * To change this template use File | Settings | File Templates.
 */
public class PKICMPMessages {

    private PKIKeyStore pkiKeyStore;

    private byte[] senderNonce;

    private byte[] transactionId;

    private BigInteger certificateID;

    private Extension[] extensions;

    private OptionalValidity optionalValidity;

    public PKICMPMessages() {
        transactionId = null;
        senderNonce = null;
        extensions = null;
        optionalValidity = null;
    }

    public PKIKeyStore getPkiKeyStore() {
        return pkiKeyStore;
    }

    public void setPkiKeyStore(PKIKeyStore keyStore) {
        this.pkiKeyStore = keyStore;
    }

    public BigInteger getCertificateID() {
        return certificateID;
    }

    public void setCertificateID(BigInteger certificateID) {
        this.certificateID = certificateID;
    }

    public void setTransactionId(byte[] transactionId) {
        this.transactionId = transactionId;
    }

    public byte[] getTransactionId() {
        return this.transactionId;
    }

    public byte[] getSenderNonce() {
        return senderNonce;
    }

    public Extension[] getExtensions() {
        return extensions;
    }

    public void setExtensions(Extension[] extensions) {
        this.extensions = extensions;
    }

    public OptionalValidity getOptionalValidity() {
        return optionalValidity;
    }

    public void setOptionalValidity(OptionalValidity optionalValidity) {
        this.optionalValidity = optionalValidity;
    }

    public void setValidity(Date notBefore, Date notAfter) {
        this.optionalValidity = new OptionalValidity(new Time(notBefore), new Time(notAfter));
    }

    private byte[] createProtectedPKIMessage(PKIBody pkiBody) throws CMPException, OperatorCreationException,
            IOException, CertificateEncodingException, PKICMPMessageException {
        senderNonce = new byte[64];

        pkiKeyStore.getSecureRandom().nextBytes(senderNonce);

        if (transactionId == null) {
            transactionId = new byte[64];
            pkiKeyStore.getSecureRandom().nextBytes(transactionId);
        }

        ContentSigner signer = new JcaContentSignerBuilder("SHA1WithRSAEncryption")
                .setProvider(pkiKeyStore.getProvider()).build(pkiKeyStore.getSenderPrivateKey());
        ProtectedPKIMessage message = new ProtectedPKIMessageBuilder(
                new GeneralName(JcaX500NameUtil.getSubject(pkiKeyStore.getSenderCertificate())),
                new GeneralName(JcaX500NameUtil.getSubject(pkiKeyStore.getRecipientCertificate())))
                        .setMessageTime(new Date()).setSenderNonce(senderNonce).setTransactionID(transactionId)
                        .addCMPCertificate(
                                new X509CertificateHolder(pkiKeyStore.getSenderCertificate().getEncoded()))
                        .setBody(pkiBody).build(signer);

        return message.toASN1Structure().getEncoded();
    }

    /**
     * Creates a certification request
     *
     * @param distinguishedName the distinguished name for the certificate
     * @param keyPair the key pair to certify, you have to remove the private key so the CA won't archive it
     * @return return the binary ASN.1 message for a certification request
     * @throws CertificateEncodingException
     * @throws CMSException
     * @throws CRMFException
     * @throws OperatorCreationException
     * @throws CMPException
     * @throws IOException
     */
    private byte[] createCertificateMessage(String distinguishedName, KeyPair keyPair, int requestType)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {

        JcaCertificateRequestMessageBuilder certReqBuild = new JcaCertificateRequestMessageBuilder(BigInteger.ZERO);

        // Basic certificate requests
        certReqBuild.setSubject(new X500Name(distinguishedName));

        // Add key pair
        if (keyPair != null) {
            byte[] bRSAKey = keyPair.getPublic().getEncoded();
            certReqBuild.setPublicKey(new SubjectPublicKeyInfo(ASN1Sequence.getInstance(bRSAKey)));
            if (keyPair.getPrivate() != null) {
                certReqBuild.addControl(
                        new JcaPKIArchiveControlBuilder(keyPair.getPrivate(), new X500Principal(distinguishedName))
                                .addRecipientGenerator(
                                        new JceKeyTransRecipientInfoGenerator(pkiKeyStore.getRecipientCertificate())
                                                .setProvider(pkiKeyStore.getProvider()))
                                .build(new JceCMSContentEncryptorBuilder(
                                        new ASN1ObjectIdentifier(CMSEnvelopedDataGenerator.DES_EDE3_CBC))
                                                .setProvider(pkiKeyStore.getProvider()).build()));
            }
        }

        if (optionalValidity != null) {
            Field field = certReqBuild.getClass().getSuperclass().getDeclaredField("templateBuilder");
            field.setAccessible(true);
            CertTemplateBuilder certTemplateBuilder = (CertTemplateBuilder) field.get(certReqBuild);
            certTemplateBuilder.setValidity(optionalValidity);
        }

        if (extensions != null) {
            for (Extension extension : extensions)
                certReqBuild.addExtension(extension.getExtnId(), extension.isCritical(),
                        extension.getParsedValue());
        }

        CertReqMessages certReqMsgs = new CertReqMessages(certReqBuild.build().toASN1Structure());

        return createProtectedPKIMessage(new PKIBody(requestType, certReqMsgs));
    }

    /**
     * Creates a initialization request, always local key generation
     *
     * @param distinguishedName the distinguished name for the certificate
     * @param keyPair the key pair to certify, you have to remove the private key so the CA won't archive it
     * @return return the binary ASN.1 message for a certification request
     * @throws CertificateEncodingException
     * @throws CMSException
     * @throws CRMFException
     * @throws OperatorCreationException
     * @throws CMPException
     * @throws IOException
     */
    public byte[] createInitializationMessage(String distinguishedName, KeyPair keyPair)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {
        return createCertificateMessage(distinguishedName, keyPair, PKIBody.TYPE_INIT_REQ);
    }

    /**
     * Creates a certification request with local key generation
     *
     * @param distinguishedName the distinguished name for the certificate
     * @param keyPair the key pair to certify, you have to remove the private key so the CA won't archive it
     * @return return the binary ASN.1 message for a certification request
     * @throws CertificateEncodingException
     * @throws CMSException
     * @throws CRMFException
     * @throws OperatorCreationException
     * @throws CMPException
     * @throws IOException
     */
    public byte[] createCertificateMessageWithLocalKey(String distinguishedName, KeyPair keyPair)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {
        return createCertificateMessage(distinguishedName, keyPair, PKIBody.TYPE_CERT_REQ);
    }

    /**
     * Creates a certification request with local key generation
     *
     * @param distinguishedName the distinguished name for the certificate
     * @return return the binary ASN.1 message for a certification request
     * @throws CertificateEncodingException
     * @throws CMSException
     * @throws CRMFException
     * @throws OperatorCreationException
     * @throws CMPException
     * @throws IOException
     */
    public byte[] createCertificateMessageWithRemoteKey(String distinguishedName)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {
        return createCertificateMessage(distinguishedName, null, PKIBody.TYPE_CERT_REQ);
    }

    /**
     * Update a certification request with local key generation
     *
     * @param certificate to be updated
     * @return return the binary ASN.1 message for a certification request
     * @throws CertificateEncodingException
     * @throws CMSException
     * @throws CRMFException
     * @throws OperatorCreationException
     * @throws CMPException
     * @throws IOException
     */
    public byte[] createKeyUpdateMessageWithLocalKey(X509Certificate certificate, KeyPair keyPair)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {
        JcaCertificateRequestMessageBuilder certReqBuild = new JcaCertificateRequestMessageBuilder(BigInteger.ZERO);
        X509CertificateHolder x509CertificateHolder = new JcaX509CertificateHolder(certificate);

        certReqBuild.setSubject(x509CertificateHolder.getSubject());
        certReqBuild.setIssuer(x509CertificateHolder.getIssuer());
        certReqBuild.setSerialNumber(x509CertificateHolder.getSerialNumber());
        if (keyPair != null) {
            certReqBuild.setPublicKey(keyPair.getPublic());
            if (keyPair.getPrivate() != null) {
                certReqBuild.addControl(
                        new JcaPKIArchiveControlBuilder(keyPair.getPrivate(), x509CertificateHolder.getIssuer())
                                .addRecipientGenerator(
                                        new JceKeyTransRecipientInfoGenerator(pkiKeyStore.getRecipientCertificate())
                                                .setProvider(pkiKeyStore.getProvider()))
                                .build(new JceCMSContentEncryptorBuilder(
                                        new ASN1ObjectIdentifier(CMSEnvelopedDataGenerator.DES_EDE3_CBC))
                                                .setProvider(pkiKeyStore.getProvider()).build()));

            }
        } else
            certReqBuild.setPublicKey(x509CertificateHolder.getSubjectPublicKeyInfo());

        if (extensions != null) {
            for (Extension extension : extensions)
                certReqBuild.addExtension(extension.getExtnId(), extension.isCritical(),
                        extension.getParsedValue());
        } else {
            if (x509CertificateHolder.getExtensions() != null) {
                for (ASN1ObjectIdentifier oid : x509CertificateHolder.getExtensions().getExtensionOIDs()) {
                    certReqBuild.addExtension(oid,
                            x509CertificateHolder.getExtensions().getExtension(oid).isCritical(),
                            x509CertificateHolder.getExtensions().getExtensionParsedValue(oid));
                }
            }
        }

        OptionalValidity tempOptionalValidity;
        if (optionalValidity != null) {
            tempOptionalValidity = optionalValidity;
        } else {
            tempOptionalValidity = new OptionalValidity(new Time(x509CertificateHolder.getNotBefore()),
                    new Time(x509CertificateHolder.getNotAfter()));
        }
        Field field = certReqBuild.getClass().getSuperclass().getDeclaredField("templateBuilder");
        field.setAccessible(true);
        CertTemplateBuilder certTemplateBuilder = (CertTemplateBuilder) field.get(certReqBuild);
        certTemplateBuilder.setValidity(tempOptionalValidity);

        CertReqMessages certReqMsgs = new CertReqMessages(certReqBuild.build().toASN1Structure());

        return createProtectedPKIMessage(new PKIBody(PKIBody.TYPE_KEY_UPDATE_REQ, certReqMsgs));
    }

    /**
     * Update a certification request with remote key generation
     *
     * @param certificate to be updated
     * @return return the binary ASN.1 message for a certification request
     * @throws CertificateEncodingException
     * @throws CMSException
     * @throws CRMFException
     * @throws OperatorCreationException
     * @throws CMPException
     * @throws IOException
     */
    public byte[] createKeyUpdateMessageWithRemoteKey(X509Certificate certificate)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {
        JcaCertificateRequestMessageBuilder certReqBuild = new JcaCertificateRequestMessageBuilder(BigInteger.ZERO);
        X509CertificateHolder x509CertificateHolder = new JcaX509CertificateHolder(certificate);

        certReqBuild.setSubject(x509CertificateHolder.getSubject());
        certReqBuild.setIssuer(x509CertificateHolder.getIssuer());
        certReqBuild.setSerialNumber(x509CertificateHolder.getSerialNumber());

        if (extensions != null) {
            for (Extension extension : extensions)
                certReqBuild.addExtension(extension.getExtnId(), extension.isCritical(),
                        extension.getParsedValue());
        } else {
            if (x509CertificateHolder.getExtensions() != null) {
                for (ASN1ObjectIdentifier oid : x509CertificateHolder.getExtensions().getExtensionOIDs()) {
                    certReqBuild.addExtension(oid,
                            x509CertificateHolder.getExtensions().getExtension(oid).isCritical(),
                            x509CertificateHolder.getExtensions().getExtensionParsedValue(oid));
                }
            }
        }

        OptionalValidity tempOptionalValidity;
        if (optionalValidity != null) {
            tempOptionalValidity = optionalValidity;
        } else {
            tempOptionalValidity = new OptionalValidity(new Time(x509CertificateHolder.getNotBefore()),
                    new Time(x509CertificateHolder.getNotAfter()));
        }
        Field field = certReqBuild.getClass().getSuperclass().getDeclaredField("templateBuilder");
        field.setAccessible(true);
        CertTemplateBuilder certTemplateBuilder = (CertTemplateBuilder) field.get(certReqBuild);
        certTemplateBuilder.setValidity(tempOptionalValidity);

        CertReqMessages certReqMsgs = new CertReqMessages(certReqBuild.build().toASN1Structure());

        return createProtectedPKIMessage(new PKIBody(PKIBody.TYPE_KEY_UPDATE_REQ, certReqMsgs));
    }

    /**
     * Revoke a certificate
     *
     */
    public byte[] createRevocationMessage(RevocationInput[] revocationInputs)
            throws CertificateEncodingException, CMSException, CRMFException, OperatorCreationException,
            CMPException, IOException, PKICMPMessageException, NoSuchFieldException, IllegalAccessException {
        List<RevDetails> revDetailsList = new ArrayList<RevDetails>(revocationInputs.length);

        for (RevocationInput revocationInput : revocationInputs) {
            List<Extension> extensions = new ArrayList<Extension>();
            X509CertificateHolder x509CertificateHolder = new JcaX509CertificateHolder(
                    revocationInput.getX509Certificate());
            CertTemplateBuilder certTemplateBuilder = new CertTemplateBuilder();

            // Template to fill in
            certTemplateBuilder.setSubject(x509CertificateHolder.getSubject())
                    .setIssuer(x509CertificateHolder.getIssuer())
                    .setSerialNumber(new ASN1Integer(x509CertificateHolder.getSerialNumber()))
                    .setPublicKey(x509CertificateHolder.getSubjectPublicKeyInfo());

            // Optional Revocation Extensions
            if (revocationInput.getReasonCode() != -1) {
                extensions.add(new Extension(Extension.reasonCode, false,
                        new ReasonFlags(revocationInput.getReasonCode()).getEncoded()));
            }
            if (revocationInput.getInvalidityDate() != null) {
                extensions.add(new Extension(Extension.invalidityDate, false,
                        new Time(revocationInput.getInvalidityDate()).getEncoded()));
            }
            if (extensions.size() == 0) {
                revDetailsList.add(new RevDetails(certTemplateBuilder.build()));
            } else {
                revDetailsList.add(new RevDetails(certTemplateBuilder.build(),
                        new Extensions(extensions.toArray(new Extension[extensions.size()]))));
            }
        }

        RevReqContent revReqContent = new RevReqContent(
                revDetailsList.toArray(new RevDetails[revDetailsList.size()]));
        return createProtectedPKIMessage(new PKIBody(PKIBody.TYPE_REVOCATION_REQ, revReqContent));
    }

    /**
     * The message to decode a certification response
     *
     * @param message
     * @return response message
     * @throws IOException
     * @throws PKICMPMessageException
     */
    PKICMPResponse processResponse(byte[] message) throws IOException, PKICMPMessageException, CertificateException,
            OperatorCreationException, CMPException, PKIKeyStoreException, ParseException {
        CertificationResult certificationResult = new CertificationResult();

        ProtectedPKIMessage pkiMessage = new ProtectedPKIMessage(new GeneralPKIMessage(message));

        /* Verify Signature */
        ContentVerifierProvider verifierProvider = new JcaContentVerifierProviderBuilder()
                .setProvider(pkiKeyStore.getProvider()).build(pkiKeyStore.getRecipientCertificate());

        if (!pkiMessage.verify(verifierProvider)) {
            throw new PKICMPMessageException("E: Verification failed this is an untrusted Message ["
                    + pkiMessage.getHeader().getSender() + "]");
        }

        if (!Arrays.equals(senderNonce, pkiMessage.getHeader().getRecipNonce().getOctets()))
            throw new PKICMPMessageException(
                    "E: Recipient Nonce in response does not correspond with Sender Nonce in request!");
        if (pkiMessage.getHeader().getMessageTime() != null) {
            pkiKeyStore.verifyCertificate(pkiKeyStore.getRecipientCertificate(),
                    pkiMessage.getHeader().getMessageTime().getDate());
        } else {
            pkiKeyStore.verifyCertificate(pkiKeyStore.getRecipientCertificate(), new Date());
        }
        PKICMPResponse pkicmpResponse = new PKICMPResponse();

        pkicmpResponse.setPkiBody(pkiMessage.getBody());
        pkicmpResponse.setPkiHeader(pkiMessage.getHeader());

        X509CertificateHolder[] x509CertificateHolders = pkiMessage.getCertificates();
        JcaX509CertificateConverter jcaX509CertificateConverter = new JcaX509CertificateConverter();
        for (X509CertificateHolder x509CertificateHolder : x509CertificateHolders) {
            pkicmpResponse.getX509CertifificateList()
                    .add(jcaX509CertificateConverter.getCertificate(x509CertificateHolder));

        }
        return pkicmpResponse;
    }

    /**
     * Process the certification in the PKIBody content. This is used by the initialization process
     * certification and keyupdate process
     *
     * @param pkiBody
     * @return
     * @throws IOException
     * @throws CMSException
     * @throws CRMFException
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     */
    CertificationResult processCertification(PKIBody pkiBody) throws IOException, CMSException, CRMFException,
            InvalidKeySpecException, NoSuchAlgorithmException, CertificateException {
        CertificationResult certificationResult = new CertificationResult();
        CertRepMessage certRepMessage = CertRepMessage.getInstance(pkiBody.getContent());
        CertResponse[] certResponses = certRepMessage.getResponse();
        certificationResult.setCertificateId(certResponses[0].getCertReqId().getValue());
        CMPCertificate certificate = certResponses[0].getCertifiedKeyPair().getCertOrEncCert().getCertificate();

        certificationResult.setX509Certificate(new JcaX509CertificateConverter()
                .getCertificate(new X509CertificateHolder(certificate.getX509v3PKCert())));

        EncryptedValue encPrivateKey = certResponses[0].getCertifiedKeyPair().getPrivateKey();
        if (encPrivateKey != null) {
            JceAsymmetricValueDecryptorGenerator jceAsymmetricValueDecryptorGenerator = new JceAsymmetricValueDecryptorGenerator(
                    pkiKeyStore.getSenderPrivateKey());
            InputDecryptor decryptor = jceAsymmetricValueDecryptorGenerator.getValueDecryptor(
                    encPrivateKey.getKeyAlg(), encPrivateKey.getSymmAlg(),
                    encPrivateKey.getEncSymmKey().getBytes());
            InputStream dataIn = decryptor
                    .getInputStream(new ByteArrayInputStream(encPrivateKey.getEncValue().getBytes()));
            byte[] data = Streams.readAll(dataIn);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(data);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");

            certificationResult.setPrivateKey(keyFactory.generatePrivate(pkcs8EncodedKeySpec));
        }

        CMPCertificate[] caPubs = certRepMessage.getCaPubs();
        for (CMPCertificate cmpCertificate : caPubs) {
            certificationResult.addX509CertificateToChain(new JcaX509CertificateConverter()
                    .getCertificate(new X509CertificateHolder(cmpCertificate.getX509v3PKCert())));
        }

        return certificationResult;
    }

    X509CRL processRevocation(PKIBody pkiBody) throws CRLException {
        JcaX509CRLConverter jcaX509CRLConverter = new JcaX509CRLConverter();

        RevRepContent revRepContent = RevRepContent.getInstance(pkiBody.getContent());

        return jcaX509CRLConverter.getCRL(new X509CRLHolder(revRepContent.getCrls()[0]));
    }

    /**
     * This creates a message to confirm a certification message
     *
     * @param x509Certificate the certificate to confirm
     * @return return the binary ASN.1 message to confirm certificate
     * @throws CertificateEncodingException
     * @throws IOException
     * @throws OperatorCreationException
     * @throws CMPException
     */
    public byte[] createConfirmationMessage(X509Certificate x509Certificate, BigInteger certificateID)
            throws CertificateEncodingException, IOException, OperatorCreationException, CMPException,
            PKICMPMessageException {
        CertificateConfirmationContentBuilder certificateConfirmationContentBuilder = new CertificateConfirmationContentBuilder();
        X509CertificateHolder x509CertificateHolder = new X509CertificateHolder(x509Certificate.getEncoded());
        certificateConfirmationContentBuilder.addAcceptedCertificate(x509CertificateHolder, certificateID);

        return createProtectedPKIMessage(
                new PKIBody(PKIBody.TYPE_CERT_CONFIRM, certificateConfirmationContentBuilder
                        .build(new JcaDigestCalculatorProviderBuilder().build()).toASN1Structure()));
    }
}