Example usage for java.security.cert X509Certificate verify

List of usage examples for java.security.cert X509Certificate verify

Introduction

In this page you can find the example usage for java.security.cert X509Certificate verify.

Prototype

public abstract void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
        InvalidKeyException, NoSuchProviderException, SignatureException;

Source Link

Document

Verifies that this certificate was signed using the private key that corresponds to the specified public key.

Usage

From source file:org.forgerock.openidm.security.impl.SecurityResourceProvider.java

/**
 * Generates a self signed certificate using the given properties.
 *
 * @param commonName the subject's common name
 * @param organization the subject's organization name
 * @param organizationUnit the subject's organization unit name
 * @param stateOrProvince the subject's state or province
 * @param country the subject's country code
 * @param locality the subject's locality
 * @param algorithm the algorithm to use
 * @param keySize the keysize to use/*ww w  .j  a v a  2  s . com*/
 * @param signatureAlgorithm the signature algorithm to use
 * @param validFrom when the certificate is valid from
 * @param validTo when the certificate is valid until
 * @return The generated certificate
 * @throws Exception
 */
protected Pair<X509Certificate, PrivateKey> generateCertificate(String commonName, String organization,
        String organizationUnit, String stateOrProvince, String country, String locality, String algorithm,
        int keySize, String signatureAlgorithm, String validFrom, String validTo) throws Exception {

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); // "RSA","BC"
    keyPairGenerator.initialize(keySize);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();

    // Generate self-signed certificate
    X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
    builder.addRDN(BCStyle.C, country);
    builder.addRDN(BCStyle.ST, stateOrProvince);
    builder.addRDN(BCStyle.L, locality);
    builder.addRDN(BCStyle.OU, organizationUnit);
    builder.addRDN(BCStyle.O, organization);
    builder.addRDN(BCStyle.CN, commonName);

    Date notBefore = null;
    Date notAfter = null;
    if (validFrom == null) {
        notBefore = new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30);
    } else {
        DateTime notBeforeDateTime = DateUtil.getDateUtil().parseIfDate(validFrom);
        if (notBeforeDateTime == null) {
            throw new InternalServerErrorException("Invalid date format for 'validFrom' property");
        } else {
            notBefore = notBeforeDateTime.toDate();
        }
    }
    if (validTo == null) {
        Calendar date = Calendar.getInstance();
        date.setTime(new Date());
        date.add(Calendar.YEAR, 10);
        notAfter = date.getTime();
    } else {
        DateTime notAfterDateTime = DateUtil.getDateUtil().parseIfDate(validTo);
        if (notAfterDateTime == null) {
            throw new InternalServerErrorException("Invalid date format for 'validTo' property");
        } else {
            notAfter = notAfterDateTime.toDate();
        }
    }

    BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());

    X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(builder.build(), serial, notBefore,
            notAfter, builder.build(), keyPair.getPublic());

    ContentSigner sigGen = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(BC)
            .build(keyPair.getPrivate());

    X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC)
            .getCertificate(v3CertGen.build(sigGen));
    cert.checkValidity(new Date());
    cert.verify(cert.getPublicKey());

    return Pair.of(cert, keyPair.getPrivate());
}

From source file:org.glite.slcs.httpclient.ssl.ExtendedX509TrustManager.java

/**
 * Returns <code>true</code> iff the certificate issuer is in our trust
 * store and it have signed the cert./*from   w ww  . j a  va  2 s  .  c o m*/
 * 
 * @param cert
 *            The X509 certificate to check.
 * @return <code>true</code> if the certificate issuer is in
 *         trustedIssuers list and have signed the cert.
 */
protected boolean isCertificateIssuerTrusted(X509Certificate cert) {
    //TODO: checks CA CRL
    // checks if an trusted issuer have signed the certificate
    boolean trusted = false;
    Iterator issuers = trustedIssuers_.iterator();
    while (issuers.hasNext()) {
        X509Certificate issuer = (X509Certificate) issuers.next();
        PublicKey issuerPublicKey = issuer.getPublicKey();
        try {
            if (LOG.isDebugEnabled()) {
                LOG.debug("checking: " + issuer.getSubjectDN());
            }
            cert.verify(issuerPublicKey);
            trusted = true;
            break;
        } catch (GeneralSecurityException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(e);
            }
        }
    }

    if (!trusted) {
        LOG.warn("No trusted issuer found in TrustStore for: " + cert.getSubjectDN());
    }

    return trusted;
}

From source file:org.globus.gsi.trustmanager.TrustedCertPathFinder.java

private static X509Certificate checkCertificate(List<X509Certificate> trustedCertPath,
        X509Certificate x509Certificate, Certificate issuerCertificate) throws CertPathValidatorException {
    X509Certificate x509IssuerCertificate = (X509Certificate) issuerCertificate;

    // check that the next one is indeed issuer, normalizing to Globus DN format
    String issuerDN = CertificateUtil.toGlobusID(x509Certificate.getIssuerX500Principal());
    String issuerCertDN = CertificateUtil.toGlobusID(x509IssuerCertificate.getSubjectX500Principal());

    if (!(issuerDN.equals(issuerCertDN))) {
        throw new IllegalArgumentException("Incorrect certificate path, certificate in chain can only "
                + "be issuer of previous certificate");
    }//from w ww .java  2s .  c  om

    // validate integrity of signature
    PublicKey publicKey = x509IssuerCertificate.getPublicKey();
    try {
        x509Certificate.verify(publicKey);
    } catch (CertificateException e) {
        throw new CertPathValidatorException(
                "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e);
    } catch (NoSuchAlgorithmException e) {
        throw new CertPathValidatorException(
                "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e);
    } catch (InvalidKeyException e) {
        throw new CertPathValidatorException(
                "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e);
    } catch (NoSuchProviderException e) {
        throw new CertPathValidatorException(
                "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e);
    } catch (SignatureException e) {
        throw new CertPathValidatorException(
                "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e);
    }

    trustedCertPath.add(x509Certificate);
    return x509IssuerCertificate;
}

From source file:org.openanzo.rdf.utils.KeystoreUtils.java

/**
 * //from   w w  w .ja  va  2s.co  m
 * @param keyStoreFile
 * @param keystoreType
 * @param password
 * @param alias
 * @param in
 * @throws AnzoException
 */
public static void addTrustedCert(String keyStoreFile, String keystoreType, String password, String alias,
        InputStream in) throws AnzoException {
    try {

        CertificateFactory cf = CertificateFactory.getInstance("X509");

        X509Certificate cert = (X509Certificate) cf.generateCertificate(in);
        if (cert.getSubjectDN().equals(cert.getIssuerDN())) {
            cert.verify(cert.getPublicKey());
        }
        addTrustedCert(keyStoreFile, keystoreType, password, alias, cert);

    } catch (Exception cce) {
        throw new AnzoException(ExceptionConstants.OSGI.INTERNAL_COMPONENT_ERROR, cce);
    }
}

From source file:org.opensc.pkcs11.spi.PKCS11KeyStoreSpi.java

private static boolean isRootCA(X509Certificate cert) throws InvalidKeyException, CertificateException,
        NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
    if (!cert.getSubjectX500Principal().equals(cert.getIssuerX500Principal()))
        return false;

    cert.verify(cert.getPublicKey());
    return true;//from ww  w . java 2  s.  c om
}

From source file:org.opensc.pkcs11.spi.PKCS11KeyStoreSpi.java

@Override
public Certificate[] engineGetCertificateChain(String name) {
    Certificate endEntity = engineGetCertificate(name);

    if (endEntity == null)
        return null;

    if (!(endEntity instanceof X509Certificate)) {
        log.error("engineGetCertificateChain: Only X.509 certificates are supported.");
        return null;
    }/*  w w w.ja  v a 2s.co  m*/

    List<Certificate> ret = new ArrayList<Certificate>();

    ret.add(endEntity);

    X509Certificate x509Certificate = (X509Certificate) endEntity;

    try {
        // OK ,this is acrude form of certificate chain evaluation.
        // Assuming, that the upper layer does a more detailed anlysis of the
        // validity period and key extensions, we only search the chain by
        // finding the issuing certificate on the token using the issuer DN
        // and trying to check the Signature on the certificate using the
        // public key on the next certificate.
        while (!isRootCA(x509Certificate)) {
            Map<String, PKCS11KSEntry> centries = getAllCertificatesForSubject(
                    x509Certificate.getIssuerX500Principal());

            X509Certificate x509NextCert = null;

            for (PKCS11KSEntry entry : centries.values()) {
                Certificate next = entry.getDecodedCertificate();

                X509Certificate x509Next = (X509Certificate) next;

                if (!x509Next.getSubjectX500Principal().equals(x509Certificate.getIssuerX500Principal()))
                    continue;

                try {
                    x509Certificate.verify(x509Next.getPublicKey());
                    x509NextCert = x509Next;
                    break;
                } catch (Exception e) {
                    log.warn("Exception during evaluation of certificate chain:", e);
                }
            }

            if (x509NextCert == null) {
                //throw new CertificateException("Cannot find the issuing CA for certificate ["+x509Certificate+"].");
                break; // to allow chains with one/leaf certificate only
            }

            x509Certificate = x509NextCert;
            ret.add(x509Certificate);
        }

        return ret.toArray(new Certificate[0]);

    } catch (Exception e) {
        log.error("Exception caught during analysis of the certificate chain:", e);
    }
    return null;
}

From source file:org.panbox.core.crypto.CryptCore.java

/**
 * Creates a self signed certificate valid for 10 years (necessary to store
 * public keys in keystore)//from w  w  w.  j av a  2s .co m
 * 
 * @param privKey
 * @param pubKey
 * @param eMail
 * @param name
 * @return the certificate or NULL if there is an error
 */
private static X509Certificate createSelfSignedX509Certificate(PrivateKey privKey, PublicKey pubKey,
        String eMail, String name) {
    // Generate self-signed certificate
    X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
    builder.addRDN(BCStyle.OU, "Panbox");
    builder.addRDN(BCStyle.O, "Panbox");
    builder.addRDN(BCStyle.CN, "localhost");

    if (eMail != null) {
        builder.addRDN(BCStyle.EmailAddress, eMail);
    }

    if (name != null) {
        builder.addRDN(BCStyle.NAME, name);
    }

    Calendar cal = Calendar.getInstance();
    Date notBefore = cal.getTime();

    cal.add(Calendar.YEAR, PanboxConstants.CERTIFICATE_LIFETIME_YEARS);
    Date notAfter = cal.getTime();

    BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());

    X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), serial, notBefore,
            notAfter, builder.build(), pubKey);

    X509Certificate cert = null;
    try {
        ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption")
                .setProvider(KeyConstants.PROV_BC).build(privKey);

        cert = new JcaX509CertificateConverter().setProvider(KeyConstants.PROV_BC)
                .getCertificate(certGen.build(sigGen));

        cert.checkValidity(new Date());

        cert.verify(cert.getPublicKey());

    } catch (NoSuchAlgorithmException | InvalidKeyException | OperatorCreationException | CertificateException
            | NoSuchProviderException | SignatureException e) {
        logger.warn("Exception caught in CryptCore.createSelfSignedX509Certificate, returning null", e);
    }

    return cert;
}

From source file:org.signserver.module.mrtdsodsigner.MRTDSODSigner.java

private void verifySignatureAndChain(final SODFile sod, final Collection<Certificate> chain)
        throws TigerSignerException {
    try {//  w w w .  j a  va  2  s .  c o m
        if (log.isDebugEnabled()) {
            final StringBuilder buff = new StringBuilder();
            buff.append("Verifying SOD signed by DS with issuer: ");
            buff.append(sod.toString());
            log.debug(buff.toString());
        }

        // Get Signer certificate from SOD
        final X509Certificate sodCert = sod.getDocSigningCertificate();

        // We need a Bouncy Castle certificate so reconstruct it
        final CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
        final X509Certificate signerCert = (X509Certificate) factory
                .generateCertificate(new ByteArrayInputStream(sodCert.getEncoded()));

        // Verify the SOD signature using certificate from SOD
        final boolean consistent = sod.checkDocSignature(signerCert);
        if (!consistent) {
            log.error("Failed to verify the SOD we signed ourselves.");
            log.error("Cert: " + signerCert);
            log.error("SOD: " + sod);
            throw new TigerSignerException("GeneralSecurityException : Signature not consistent");
        }

        // Find the issuer certificate from the configured chain
        final X509Certificate issuerCert = (chain == null ? null : findIssuerCert(chain, signerCert));
        if (issuerCert == null) {
            log.error("Failed to verify certificate chain");
            log.error("Cert: " + signerCert);
            log.error("SOD Cert: " + signerCert);
            log.error("Chain: " + chain);
            throw new TigerSignerException("GeneralSecurityException :Issuer of cert not in chain.");
        }

        // Verify the signer certificate using the issuer from the chain
        signerCert.verify(issuerCert.getPublicKey());
    } catch (IOException e) {
        log.error("Getting signer certificate from SOD failed", e);
        throw new TigerSignerException("GeneralSecurityException : Getting signer certificate from SOD failed",
                e);
    } catch (CertificateEncodingException e) {
        throw new TigerSignerException("CertificateEncodingException : ", e);
    } catch (CertificateException e) {
        throw new TigerSignerException("CertificateException : ", e);
    } catch (NoSuchAlgorithmException e) {
        throw new TigerSignerException("NoSuchAlgorithmException : ", e);
    } catch (InvalidKeyException e) {
        throw new TigerSignerException("InvalidKeyException : ", e);
    } catch (SignatureException e) {
        throw new TigerSignerException("SignatureException : ", e);
    } catch (NoSuchProviderException e) {
        throw new TigerSignerException("NoSuchProviderException : ", e);
    } catch (GeneralSecurityException e) {
        throw new TigerSignerException("GeneralSecurityException : ", e);
    }
}

From source file:org.texai.x509.X509Utils.java

/** Generates an intermediate CA certificate, that is to be used to sign end-use certificates.
 *
 * @param myPublicKey the public key for this certificate
 * @param issuerPrivateKey the issuer's private key
 * @param issuerCertificate the issuer's certificate, which is either the root CA certificate or another intermediate
 * CA certificate//from  ww w  .  j  a v  a  2s.c  om
 * @param pathLengthConstraint the maximum number of CA certificates that may follow this certificate in a certification
 * path. (Note: One end-entity certificate will follow the final CA certificate in the path. The last certificate in a path
 * is considered an end-entity certificate, whether the subject of the certificate is a CA or not.)
 * @return an intermediate CA certificate
 *
 * @throws CertificateParsingException when the certificate cannot be parsed
 * @throws CertificateEncodingException when the certificate cannot be encoded
 * @throws NoSuchProviderException when an invalid provider is given
 * @throws NoSuchAlgorithmException when an invalid algorithm is given
 * @throws SignatureException when the an invalid signature is present
 * @throws InvalidKeyException when the given key is invalid
 * @throws IOException if an input/output error occurs while processing the serial number file
 */
public static X509Certificate generateIntermediateX509Certificate(final PublicKey myPublicKey,
        final PrivateKey issuerPrivateKey, final X509Certificate issuerCertificate, int pathLengthConstraint)
        throws CertificateParsingException, CertificateEncodingException, NoSuchProviderException,
        NoSuchAlgorithmException, SignatureException, InvalidKeyException, IOException {
    //Preconditions
    assert myPublicKey != null : "myPublicKey must not be null";
    assert issuerPrivateKey != null : "issuerPrivateKey must not be null";
    assert issuerCertificate != null : "issuerCertificate must not be null";

    //final X500Name issuer = new X500Name(issuerCertificate.getSubjectX500Principal().getName());
    final X500Name issuer = new X500Name(
            StringUtils.reverseCommaDelimitedString(issuerCertificate.getSubjectX500Principal().getName()));
    final UUID intermediateUUID = UUID.randomUUID();
    // provide items to X500Principal in reverse order
    final X500Principal x500Principal = new X500Principal(
            "UID=" + intermediateUUID + ", DC=IntermediateCertificate, CN=texai.org");
    final X500Name subject = new X500Name(x500Principal.getName());
    SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(
            ASN1Sequence.getInstance(myPublicKey.getEncoded()));
    final X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(issuer,
            getNextSerialNumber(), // serial
            new Date(System.currentTimeMillis() - 10000L), // notBefore,
            new Date(System.currentTimeMillis() + VALIDITY_PERIOD), // notAfter,
            subject, publicKeyInfo);

    // see http://www.ietf.org/rfc/rfc3280.txt
    // see http://stackoverflow.com/questions/20175447/creating-certificates-for-ssl-communication
    final JcaX509ExtensionUtils jcaX509ExtensionUtils = new JcaX509ExtensionUtils();

    // Add authority key identifier
    x509v3CertificateBuilder.addExtension(Extension.authorityKeyIdentifier, false, // isCritical
            jcaX509ExtensionUtils.createAuthorityKeyIdentifier(issuerCertificate));

    // Add subject key identifier
    x509v3CertificateBuilder.addExtension(Extension.subjectKeyIdentifier, false, // isCritical
            jcaX509ExtensionUtils.createSubjectKeyIdentifier(myPublicKey));

    // add basic constraints
    x509v3CertificateBuilder.addExtension(Extension.basicConstraints, true, // isCritical
            new BasicConstraints(pathLengthConstraint)); // is a CA certificate with specified certification path length

    // add key usage
    final KeyUsage keyUsage = new KeyUsage(
            // the keyCertSign bit indicates that the subject public key may be used for verifying a signature on
            // certificates
            KeyUsage.keyCertSign | // the cRLSign indicates that the subject public key may be used for verifying a signature on revocation
                                   // information
                    KeyUsage.cRLSign);

    x509v3CertificateBuilder.addExtension(Extension.keyUsage, true, // isCritical
            keyUsage);

    X509Certificate x509Certificate;
    try {
        final ContentSigner contentSigner = new JcaContentSignerBuilder(DIGITAL_SIGNATURE_ALGORITHM)
                .setProvider(BOUNCY_CASTLE_PROVIDER).build(issuerPrivateKey);
        final X509CertificateHolder x509CertificateHolder = x509v3CertificateBuilder.build(contentSigner);
        final JcaX509CertificateConverter jcaX509CertificateConverter = new JcaX509CertificateConverter();
        x509Certificate = makeCanonicalX509Certificate(
                jcaX509CertificateConverter.getCertificate(x509CertificateHolder));
    } catch (CertificateException | OperatorCreationException ex) {
        throw new TexaiException(ex);
    }

    //Postconditions
    try {
        x509Certificate.checkValidity();
        x509Certificate.verify(issuerCertificate.getPublicKey());
    } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException
            | SignatureException ex) {
        throw new TexaiException(ex);
    }

    return x509Certificate;
}

From source file:org.texai.x509.X509Utils.java

/** Generates a signed end-use certificate that cannot be used to sign other certificates, but can be used for authentication
 * and for message signing.//from w  w w  .  j av  a2  s .c  om
 *
 * @param myPublicKey the public key for this certificate
 * @param issuerPrivateKey the issuer's private key
 * @param issuerCertificate the issuer's certificate
 * @param uid the subject UID
 * @param domainComponent the domain component, e.g. TexaiLauncher or NodeRuntime
 * @return a signed end-use certificate
 *
 * @throws CertificateParsingException when the certificate cannot be parsed
 * @throws CertificateEncodingException when the certificate cannot be encoded
 * @throws NoSuchProviderException when an invalid provider is given
 * @throws NoSuchAlgorithmException when an invalid algorithm is given
 * @throws SignatureException when the an invalid signature is present
 * @throws InvalidKeyException when the given key is invalid
 * @throws IOException if an input/output error occurs while processing the serial number file
 */
public static X509Certificate generateX509Certificate(final PublicKey myPublicKey,
        final PrivateKey issuerPrivateKey, final X509Certificate issuerCertificate, final UUID uid,
        final String domainComponent)
        throws CertificateParsingException, CertificateEncodingException, NoSuchProviderException,
        NoSuchAlgorithmException, SignatureException, InvalidKeyException, IOException {
    //Preconditions
    assert myPublicKey != null : "myPublicKey must not be null";
    assert issuerPrivateKey != null : "issuerPrivateKey must not be null";
    assert issuerCertificate != null : "issuerCertificate must not be null";
    assert uid != null : "uid must not be null";

    final String x500PrincipalString;
    // provide items to X500Principal in reverse order
    if (domainComponent == null || domainComponent.isEmpty()) {
        x500PrincipalString = "UID=" + uid + ", CN=texai.org";
    } else {
        x500PrincipalString = "UID=" + uid + ", DC=" + domainComponent + " ,CN=texai.org";
    }
    final X500Principal x500Principal = new X500Principal(x500PrincipalString);

    LOGGER.info("issuer: " + issuerCertificate.getIssuerX500Principal().getName());

    final X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(
            new X500Name(StringUtils
                    .reverseCommaDelimitedString(issuerCertificate.getSubjectX500Principal().getName())), // issuer,
            getNextSerialNumber(), // serial
            new Date(System.currentTimeMillis() - 10000L), // notBefore,
            new Date(System.currentTimeMillis() + VALIDITY_PERIOD), // notAfter,
            new X500Name(x500Principal.getName()), // subject,
            new SubjectPublicKeyInfo(ASN1Sequence.getInstance(myPublicKey.getEncoded()))); // publicKeyInfo

    // see http://www.ietf.org/rfc/rfc3280.txt
    // see http://stackoverflow.com/questions/20175447/creating-certificates-for-ssl-communication
    final JcaX509ExtensionUtils jcaX509ExtensionUtils = new JcaX509ExtensionUtils();
    // Add authority key identifier
    x509v3CertificateBuilder.addExtension(Extension.authorityKeyIdentifier, false, // isCritical
            jcaX509ExtensionUtils.createAuthorityKeyIdentifier(issuerCertificate));

    // Add subject key identifier
    x509v3CertificateBuilder.addExtension(Extension.subjectKeyIdentifier, false, // isCritical
            jcaX509ExtensionUtils.createSubjectKeyIdentifier(myPublicKey));

    // add basic constraints
    x509v3CertificateBuilder.addExtension(Extension.basicConstraints, true, // isCritical
            new BasicConstraints(false)); // is not a CA certificate

    // add key usage
    final KeyUsage keyUsage = new KeyUsage(
            // the digitalSignature usage indicates that the subject public key may be used with a digital signature
            // mechanism to support security services other than non-repudiation, certificate signing, or revocation
            // information signing
            KeyUsage.digitalSignature | // the nonRepudiation usage indicates that the subject public key may be used to verify digital signatures
                                        // used to provide a non-repudiation service which protects against the signing entity falsely denying some
                                        // action, excluding certificate or CRL signing
                    KeyUsage.nonRepudiation | // the keyEncipherment usage indicates that the subject public key may be used for key transport, e.g. the
                                              // exchange of efficient symmetric keys in SSL
                    KeyUsage.keyEncipherment | // the dataEncipherment usage indicates that the subject public key may be used for enciphering user data,
                                               // other than cryptographic keys
                    KeyUsage.dataEncipherment | // the keyAgreement usage indicates that the subject public key may be used for key agreement, e.g. when a
                                                // Diffie-Hellman key is to be used for key management
                    KeyUsage.keyAgreement | // the keyCertSign bit indicates that the subject public key may be used for verifying a signature on
                                            // certificates
                    KeyUsage.keyCertSign | // the cRLSign indicates that the subject public key may be used for verifying a signature on revocation
                                           // information
                    KeyUsage.cRLSign | // see http://www.docjar.com/html/api/sun/security/validator/EndEntityChecker.java.html - bit 0 needs to set for SSL
                                       // client authorization
                    KeyUsage.encipherOnly);
    x509v3CertificateBuilder.addExtension(Extension.keyUsage, true, // isCritical
            keyUsage);

    X509Certificate x509Certificate;
    try {
        final ContentSigner contentSigner = new JcaContentSignerBuilder(DIGITAL_SIGNATURE_ALGORITHM)
                .setProvider(BOUNCY_CASTLE_PROVIDER).build(issuerPrivateKey);
        final X509CertificateHolder x509CertificateHolder = x509v3CertificateBuilder.build(contentSigner);
        final JcaX509CertificateConverter jcaX509CertificateConverter = new JcaX509CertificateConverter();
        x509Certificate = makeCanonicalX509Certificate(
                jcaX509CertificateConverter.getCertificate(x509CertificateHolder));
    } catch (CertificateException | OperatorCreationException ex) {
        throw new TexaiException(ex);
    }

    //Postconditions
    try {
        x509Certificate.checkValidity();
        x509Certificate.verify(issuerCertificate.getPublicKey());
    } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException
            | SignatureException ex) {
        throw new TexaiException(ex);
    }
    assert x509Certificate.getKeyUsage()[0] : "must have digital signature key usage";

    return x509Certificate;
}