Example usage for org.bouncycastle.asn1.x509 Extension subjectKeyIdentifier

List of usage examples for org.bouncycastle.asn1.x509 Extension subjectKeyIdentifier

Introduction

In this page you can find the example usage for org.bouncycastle.asn1.x509 Extension subjectKeyIdentifier.

Prototype

ASN1ObjectIdentifier subjectKeyIdentifier

To view the source code for org.bouncycastle.asn1.x509 Extension subjectKeyIdentifier.

Click Source Link

Document

Subject Key Identifier

Usage

From source file:org.openestate.tool.server.utils.SslGenerator.java

License:Apache License

/**
 * Start SSL initialization./*from  www .ja  v  a  2 s  .c om*/
 *
 * @param args command line arguments,
 *             the first argument might contain the common name,
 *             the second argument might contain the keystore password
 */
@SuppressWarnings("Duplicates")
public static void main(String[] args) {
    final Console console = System.console();
    final String line = StringUtils.repeat("-", 75);

    console.writer().println(StringUtils.EMPTY);
    console.writer().println(line);
    console.writer().println(I18N.tr("Generate RSA key pair and certificate for SSL encryption."));
    console.writer().println(line);
    console.writer().println(StringUtils.EMPTY);

    // register bouncy castle provider
    Security.addProvider(new BouncyCastleProvider());

    // get common name
    String commonName = (args.length > 0) ? StringUtils.trimToNull(args[0]) : null;
    while (commonName == null) {
        //LOGGER.error( "No common name was specified as first command line argument!" );
        //System.exit( 1 );
        //return;

        console.writer().print(I18N.tr("Enter the ip-address / hostname of this server:") + StringUtils.SPACE);
        console.writer().flush();
        commonName = StringUtils.trimToNull(console.readLine());
    }

    // get password
    char[] password = (args.length > 1) ? StringUtils.trimToEmpty(args[1]).toCharArray() : null;
    if (password == null) {
        //LOGGER.error( "No password was specified as second command line argument!" );
        //System.exit( 1 );
        //return;

        while (password == null) {
            console.writer().print(I18N.tr("Enter the password to access the keystore:") + StringUtils.SPACE);
            console.writer().flush();
            password = console.readPassword();
        }

        console.writer().print(I18N.tr("Enter the password to access the keystore again:") + StringUtils.SPACE);
        console.writer().flush();
        char[] password2 = console.readPassword();
        if (!StringUtils.equals(String.valueOf(password), String.valueOf(password2))) {
            console.writer().println(StringUtils.capitalize(I18N.tr("error")) + "!");
            console.writer().println(I18N.tr("The provided passwords do not match."));
            System.exit(1);
        }
    }

    console.writer().println(StringUtils.EMPTY);
    console.writer().println(line);
    console.writer().println(I18N.tr("Creating files for SSL encryption..."));
    console.writer().println(line);
    console.writer().println(StringUtils.EMPTY);

    final File etcDir;
    final File sslDir;
    try {
        etcDir = ServerUtils.getEtcDir();
        sslDir = new File(etcDir, "ssl");
    } catch (IOException ex) {
        LOGGER.error("Can't locate ssl directory!");
        System.exit(1);
        return;
    }
    if (!sslDir.exists() && !sslDir.mkdirs()) {
        LOGGER.error("Can't create ssl directory at '" + sslDir.getAbsolutePath() + "'!");
        System.exit(1);
        return;
    }

    // create random number generator
    final SecureRandom random = new SecureRandom();

    // create key generator
    final KeyPairGenerator keyGen;
    try {
        keyGen = KeyPairGenerator.getInstance(KEY_ALGORITHM, PROVIDER);
        keyGen.initialize(KEY_LENGTH, random);
    } catch (Exception ex) {
        LOGGER.error("Can't initialize key generator!");
        LOGGER.error("> " + ex.getLocalizedMessage(), ex);
        System.exit(1);
        return;
    }

    // generate a key pair
    final KeyPair pair = keyGen.generateKeyPair();

    // export private key
    final PrivateKey privateKey = pair.getPrivate();
    final File privateKeyFile = new File(sslDir, "private.key");
    FileUtils.deleteQuietly(privateKeyFile);
    console.writer()
            .println(I18N.tr("Writing private key to {0}.", "'" + privateKeyFile.getAbsolutePath() + "'"));
    try (PemWriter pemWriter = new PemWriter(new FileWriterWithEncoding(privateKeyFile, "UTF-8"))) {
        pemWriter.writeObject(new PemObject(ALIAS + " / Private Key", privateKey.getEncoded()));
        pemWriter.flush();
    } catch (Exception ex) {
        LOGGER.error("Can't export private key!");
        LOGGER.error("> " + ex.getLocalizedMessage(), ex);
        System.exit(1);
        return;
    }

    // export public key
    final PublicKey publicKey = pair.getPublic();
    final File publicKeyFile = new File(sslDir, "public.key");
    FileUtils.deleteQuietly(publicKeyFile);
    console.writer()
            .println(I18N.tr("Writing public key to {0}.", "'" + publicKeyFile.getAbsolutePath() + "'"));
    try (PemWriter pemWriter = new PemWriter(new FileWriterWithEncoding(publicKeyFile, "UTF-8"))) {
        pemWriter.writeObject(new PemObject(ALIAS + " / Public Key", publicKey.getEncoded()));
        pemWriter.flush();
    } catch (Exception ex) {
        LOGGER.error("Can't export public key!");
        LOGGER.error("> " + ex.getLocalizedMessage(), ex);
        System.exit(1);
        return;
    }

    // generate certificate
    final X509Certificate cert;
    try {
        Date startDate = new Date();
        Date expiryDate = DateUtils.addYears(startDate, 10);
        X500Name subject = new X500Name("CN=" + commonName);
        SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
        BigInteger serial = BigInteger.valueOf(random.nextLong()).abs();

        //X509v1CertificateBuilder builder = new X509v1CertificateBuilder( subject, serial, startDate, expiryDate, subject, publicKeyInfo );
        //X509CertificateHolder holder = builder.build( createSigner( privateKey ) );
        //cert = new JcaX509CertificateConverter().getCertificate( holder );

        X509v3CertificateBuilder builder = new X509v3CertificateBuilder(subject, serial, startDate, expiryDate,
                subject, publicKeyInfo);

        X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(
                new BcDigestCalculatorProvider().get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)));
        builder.addExtension(Extension.subjectKeyIdentifier, false,
                x509ExtensionUtils.createSubjectKeyIdentifier(publicKeyInfo));

        X509CertificateHolder holder = builder.build(createSigner(privateKey));
        cert = new JcaX509CertificateConverter().getCertificate(holder);

        // export certificate
        File f = new File(sslDir, "private.crt");
        FileUtils.deleteQuietly(f);
        console.writer().println(I18N.tr("Writing certificate to {0}.", "'" + f.getAbsolutePath() + "'"));
        try (PemWriter pemWriter = new PemWriter(new FileWriterWithEncoding(f, "UTF-8"))) {
            pemWriter.writeObject(new PemObject(ALIAS + " / Certificate", cert.getEncoded()));
            pemWriter.flush();
        }
    } catch (Exception ex) {
        LOGGER.error("Can't create certificate!");
        LOGGER.error("> " + ex.getLocalizedMessage(), ex);
        System.exit(1);
        return;
    }

    // create keystore
    try {
        KeyStore store = KeyStore.getInstance("jks");
        store.load(null, password);
        store.setKeyEntry(ALIAS, privateKey, password, new Certificate[] { cert });

        File f = new File(sslDir, "keystore.jks");
        FileUtils.deleteQuietly(f);
        console.writer().println(I18N.tr("Writing keystore to {0}.", "'" + f.getAbsolutePath() + "'"));

        try (OutputStream output = new FileOutputStream(f)) {
            store.store(output, password);
            output.flush();
        }
    } catch (Exception ex) {
        LOGGER.error("Can't create keystore!");
        LOGGER.error("> " + ex.getLocalizedMessage(), ex);
        System.exit(1);
        return;
    }

    console.writer().println(StringUtils.EMPTY);
    console.writer().println(line);
    console.writer().println(I18N.tr("SSL encryption was successfully prepared!"));
    console.writer().println(line);
    console.writer().println(StringUtils.EMPTY);
    console.writer().println(I18N.tr("Follow these steps in order to enable SSL encryption."));
    console.writer().println(StringUtils.EMPTY);
    console.writer().println("(1) " + I18N.tr("Open the following configuration file with a text editor:"));
    console.writer().println(StringUtils.EMPTY);
    console.writer().println(new File(etcDir, "server.properties").getAbsolutePath());
    console.writer().println(StringUtils.EMPTY);
    console.writer().println("(2) " + I18N.tr("Change the following values in the configuration file:"));
    console.writer().println(StringUtils.EMPTY);
    console.writer().println("server.tls=true");
    //console.writer().println("system.javax.net.ssl.keyStore=./etc/ssl/keystore.jks");
    console.writer().println("system.javax.net.ssl.keyStorePassword=" + String.valueOf(password));
    console.writer().println(StringUtils.EMPTY);
    console.writer().println("(3) " + I18N.tr("Restart {0}.", ServerUtils.TITLE));
    console.writer().println(StringUtils.EMPTY);
    console.writer().println(line);
    console.writer().println(StringUtils.EMPTY);

    console.writer().println(I18N.tr("Press ENTER to exit this application."));
    try {
        console.readLine();
    } catch (Exception ignored) {
    }
}

From source file:org.openfact.common.util.CertificateUtils.java

License:Apache License

/**
 * Generates version 3 {@link X509Certificate}.
 *
 * @param keyPair the key pair//from w  w  w .ja va  2s.co m
 * @param caPrivateKey the CA private key
 * @param caCert the CA certificate
 * @param subject the subject name
 *
 * @return the x509 certificate
 *
 * @throws Exception the exception
 */
public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey,
        X509Certificate caCert, String subject) throws Exception {

    try {
        X500Name subjectDN = new X500Name("CN=" + subject);

        // Serial Number
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));

        // Validity
        Date notBefore = new Date(System.currentTimeMillis());
        Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);

        // SubjectPublicKeyInfo
        SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(
                ASN1Sequence.getInstance(keyPair.getPublic().getEncoded()));

        X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(
                new X500Name(caCert.getSubjectDN().getName()), serialNumber, notBefore, notAfter, subjectDN,
                subjPubKeyInfo);

        DigestCalculator digCalc = new BcDigestCalculatorProvider()
                .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
        X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);

        // Subject Key Identifier
        certGen.addExtension(Extension.subjectKeyIdentifier, false,
                x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));

        // Authority Key Identifier
        certGen.addExtension(Extension.authorityKeyIdentifier, false,
                x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));

        // Key Usage
        certGen.addExtension(Extension.keyUsage, false,
                new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign));

        // Extended Key Usage
        KeyPurposeId[] EKU = new KeyPurposeId[2];
        EKU[0] = KeyPurposeId.id_kp_emailProtection;
        EKU[1] = KeyPurposeId.id_kp_serverAuth;

        certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));

        // Basic Constraints
        certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));

        // Content Signer
        ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC")
                .build(caPrivateKey);

        // Certificate
        return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
    } catch (Exception e) {
        throw new RuntimeException("Error creating X509v3Certificate.", e);
    }
}

From source file:org.parosproxy.paros.security.SslCertificateServiceImpl.java

License:Apache License

@Override
public KeyStore createCertForHost(String hostname)
        throws NoSuchAlgorithmException, InvalidKeyException, CertificateException, NoSuchProviderException,
        SignatureException, KeyStoreException, IOException, UnrecoverableKeyException {

    if (hostname == null) {
        throw new IllegalArgumentException("Error, 'hostname' is not allowed to be null!");
    }/*w  w w.  j av  a 2 s .  c  om*/

    if (this.caCert == null || this.caPrivKey == null || this.caPubKey == null) {
        throw new MissingRootCertificateException(
                this.getClass() + " wasn't initialized! Got to options 'Dynamic SSL Certs' and create one.");
    }

    final KeyPair mykp = this.createKeyPair();
    final PrivateKey privKey = mykp.getPrivate();
    final PublicKey pubKey = mykp.getPublic();

    X500NameBuilder namebld = new X500NameBuilder(BCStyle.INSTANCE);
    namebld.addRDN(BCStyle.CN, hostname);
    namebld.addRDN(BCStyle.OU, "Zed Attack Proxy Project");
    namebld.addRDN(BCStyle.O, "OWASP");
    namebld.addRDN(BCStyle.C, "xx");
    namebld.addRDN(BCStyle.EmailAddress, "owasp-zed-attack-proxy@lists.owasp.org");

    X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
            new X509CertificateHolder(caCert.getEncoded()).getSubject(),
            BigInteger.valueOf(serial.getAndIncrement()),
            new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30),
            new Date(System.currentTimeMillis() + 100 * (1000L * 60 * 60 * 24 * 30)), namebld.build(), pubKey);

    certGen.addExtension(Extension.subjectKeyIdentifier, false, new SubjectKeyIdentifier(pubKey.getEncoded()));
    certGen.addExtension(Extension.basicConstraints, false, new BasicConstraints(false));

    ContentSigner sigGen;
    try {
        sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider("BC").build(caPrivKey);
    } catch (OperatorCreationException e) {
        throw new CertificateException(e);
    }
    final X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC")
            .getCertificate(certGen.build(sigGen));
    cert.checkValidity(new Date());
    cert.verify(caPubKey);

    final KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(null, null);
    final Certificate[] chain = new Certificate[2];
    chain[1] = this.caCert;
    chain[0] = cert;
    ks.setKeyEntry(ZAPROXY_JKS_ALIAS, privKey, PASSPHRASE, chain);
    return ks;
}

From source file:org.picketlink.pki.internal.util.X509Util.java

License:Open Source License

/**
 * Generate version 3 {@link java.security.cert.X509Certificate}.
 *
 * @param rootCertificate the root certificate
 * @param issuerKeyPair the issuer key pair
 * @param subjectDN the subject dn/*ww  w. j  av  a2 s. com*/
 * @param subjectKeyPair the subject key pair
 * @param certificateConfig the certificate config
 *
 * @return the x509 certificate
 */
public static X509Certificate generateV3Certificate(X509Certificate rootCertificate, KeyPair issuerKeyPair,
        X500Name subjectDN, KeyPair subjectKeyPair, CertificateAuthorityConfig certificateConfig) {
    try {
        // Serial Number
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));

        // Validity
        Date notBefore = new Date(System.currentTimeMillis());
        Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);

        // SubjectPublicKeyInfo
        SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(
                ASN1Sequence.getInstance(subjectKeyPair.getPublic().getEncoded()));

        X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(
                new X500Name(rootCertificate.getSubjectDN().getName()), serialNumber, notBefore, notAfter,
                subjectDN, subjPubKeyInfo);

        DigestCalculator digCalc = new BcDigestCalculatorProvider()
                .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
        X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);

        // Subject Key Identifier
        certGen.addExtension(Extension.subjectKeyIdentifier, false,
                x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));

        // Authority Key Identifier
        certGen.addExtension(Extension.authorityKeyIdentifier, false,
                x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));

        // Key Usage
        certGen.addExtension(Extension.keyUsage, false,
                new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign));

        // Extended Key Usage
        KeyPurposeId[] EKU = new KeyPurposeId[2];
        EKU[0] = KeyPurposeId.id_kp_emailProtection;
        EKU[1] = KeyPurposeId.id_kp_serverAuth;

        certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));

        // Basic Constraints
        certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));

        // Certificate Policies
        /* PolicyInformation[] certPolicies = new PolicyInformation[2];
        certPolicies[0] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.5"));
        certPolicies[1] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.18"));
                
        certGen.addExtension(Extension.certificatePolicies, false, new CertificatePolicies(certPolicies));
                
        // Authority Information Access
        AccessDescription caIssuers = new AccessDescription(AccessDescription.id_ad_caIssuers, new GeneralName(
            GeneralName.uniformResourceIdentifier, new DERIA5String("http://www.somewebsite.com/ca.cer")));
        AccessDescription ocsp = new AccessDescription(AccessDescription.id_ad_ocsp, new GeneralName(
            GeneralName.uniformResourceIdentifier, new DERIA5String("http://ocsp.somewebsite.com")));
                
        ASN1EncodableVector aia_ASN = new ASN1EncodableVector();
        aia_ASN.add(caIssuers);
        aia_ASN.add(ocsp);
                
        certGen.addExtension(Extension.authorityInfoAccess, false, new DERSequence(aia_ASN));
                
        // CRL Distribution Points
        DistributionPointName distPointOne = new DistributionPointName(new GeneralNames(new GeneralName(
            GeneralName.uniformResourceIdentifier, "http://crl.somewebsite.com/master.crl")));
        DistributionPointName distPointTwo = new DistributionPointName(
            new GeneralNames(
                    new GeneralName(GeneralName.uniformResourceIdentifier,
                            "ldap://crl.somewebsite.com/cn%3dSecureCA%2cou%3dPKI%2co%3dCyberdyne%2cc%3dUS?certificaterevocationlist;binary")));
                
        DistributionPoint[] distPoints = new DistributionPoint[2];
        distPoints[0] = new DistributionPoint(distPointOne, null, null);
        distPoints[1] = new DistributionPoint(distPointTwo, null, null);
                
        certGen.addExtension(Extension.cRLDistributionPoints, false, new CRLDistPoint(distPoints));*/

        // Content Signer
        ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC")
                .build(issuerKeyPair.getPrivate());

        // Certificate
        return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
    } catch (Exception e) {
        throw new RuntimeException("Error creating X509v3Certificate.", e);
    }
}

From source file:org.tdmx.client.crypto.certificate.CredentialUtils.java

License:Open Source License

/**
 * Create the credentials of a ZoneAdministrator.
 * // w  w w . j  a  v a  2 s  .c  om
 * The ZoneAdministrator credentials are long validity.
 * 
 * @param req
 * @return
 * @throws CryptoCertificateException
 */
public static PKIXCredential createZoneAdministratorCredential(ZoneAdministrationCredentialSpecifier req)
        throws CryptoCertificateException {
    KeyPair kp = null;
    try {
        kp = req.getKeyAlgorithm().generateNewKeyPair();
    } catch (CryptoException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_KEYPAIR_GENERATION, e);
    }

    PublicKey publicKey = kp.getPublic();
    PrivateKey privateKey = kp.getPrivate();

    X500NameBuilder subjectBuilder = new X500NameBuilder();
    if (StringUtils.hasText(req.getCountry())) {
        subjectBuilder.addRDN(BCStyle.C, req.getCountry());
    }
    if (StringUtils.hasText(req.getLocation())) {
        subjectBuilder.addRDN(BCStyle.L, req.getLocation());
    }
    if (StringUtils.hasText(req.getOrg())) {
        subjectBuilder.addRDN(BCStyle.O, req.getOrg());
    }
    if (StringUtils.hasText(req.getOrgUnit())) {
        if (TDMX_DOMAIN_CA_OU.equals(req.getOrgUnit())) {
            throw new CryptoCertificateException(CertificateResultCode.ERROR_INVALID_OU);
        }
        subjectBuilder.addRDN(BCStyle.OU, req.getOrgUnit());
    }
    if (StringUtils.hasText(req.getEmailAddress())) {
        subjectBuilder.addRDN(BCStyle.E, req.getEmailAddress());
    }
    if (StringUtils.hasText(req.getTelephoneNumber())) {
        subjectBuilder.addRDN(BCStyle.TELEPHONE_NUMBER, req.getTelephoneNumber());
    }
    if (StringUtils.hasText(req.getCn())) {
        subjectBuilder.addRDN(BCStyle.CN, req.getCn());
    }
    X500Name subject = subjectBuilder.build();
    X500Name issuer = subject;
    JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(issuer, new BigInteger("1"),
            req.getNotBefore().getTime(), req.getNotAfter().getTime(), subject, publicKey);

    try {
        BasicConstraints cA = new BasicConstraints(1);
        certBuilder.addExtension(Extension.basicConstraints, true, cA);

        JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
        certBuilder.addExtension(Extension.authorityKeyIdentifier, false,
                extUtils.createAuthorityKeyIdentifier(publicKey));
        certBuilder.addExtension(Extension.subjectKeyIdentifier, false,
                extUtils.createSubjectKeyIdentifier(publicKey));

        KeyUsage ku = new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign);
        certBuilder.addExtension(Extension.keyUsage, false, ku);

        // RFC5280 http://tools.ietf.org/html/rfc5280#section-4.2.1.10
        // The CA has a CN which is not part of the name constraint - but we can constrain
        // any domain certificate issued to be limited to some OU under the O.
        X500NameBuilder subjectConstraintBuilder = new X500NameBuilder();
        if (StringUtils.hasText(req.getCountry())) {
            subjectConstraintBuilder.addRDN(BCStyle.C, req.getCountry());
        }
        if (StringUtils.hasText(req.getLocation())) {
            subjectConstraintBuilder.addRDN(BCStyle.L, req.getLocation());
        }
        if (StringUtils.hasText(req.getOrg())) {
            subjectConstraintBuilder.addRDN(BCStyle.O, req.getOrg());
        }
        if (StringUtils.hasText(req.getOrgUnit())) {
            subjectConstraintBuilder.addRDN(BCStyle.OU, req.getOrgUnit());
        }
        subjectConstraintBuilder.addRDN(BCStyle.OU, TDMX_DOMAIN_CA_OU);
        X500Name nameConstraint = subjectConstraintBuilder.build();

        GeneralName snc = new GeneralName(GeneralName.directoryName, nameConstraint);
        GeneralSubtree snSubtree = new GeneralSubtree(snc, new BigInteger("0"), null);
        NameConstraints nc = new NameConstraints(new GeneralSubtree[] { snSubtree }, null);
        certBuilder.addExtension(Extension.nameConstraints, true, nc);

        certBuilder.addExtension(TdmxZoneInfo.tdmxZoneInfo, false, req.getZoneInfo());

        ContentSigner signer = SignatureAlgorithm.getContentSigner(privateKey, req.getSignatureAlgorithm());
        byte[] certBytes = certBuilder.build(signer).getEncoded();

        PKIXCertificate c = CertificateIOUtils.decodeX509(certBytes);

        return new PKIXCredential(c, privateKey);
    } catch (CertIOException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    } catch (NoSuchAlgorithmException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    } catch (IOException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    }
}

From source file:org.tdmx.client.crypto.certificate.CredentialUtils.java

License:Open Source License

/**
 * Create the credentials of a DomainAdministrator.
 * /*ww w.j ava 2 s . c  o  m*/
 * @param req
 * @return
 * @throws CryptoCertificateException
 */
public static PKIXCredential createDomainAdministratorCredential(DomainAdministrationCredentialSpecifier req)
        throws CryptoCertificateException {
    KeyPair kp = null;
    try {
        kp = req.getKeyAlgorithm().generateNewKeyPair();
    } catch (CryptoException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_KEYPAIR_GENERATION, e);
    }

    PublicKey publicKey = kp.getPublic();
    PrivateKey privateKey = kp.getPrivate();

    PKIXCredential issuerCredential = req.getZoneAdministratorCredential();
    PKIXCertificate issuerPublicCert = issuerCredential.getPublicCert();

    PublicKey issuerPublicKey = issuerPublicCert.getCertificate().getPublicKey();
    PrivateKey issuerPrivateKey = issuerCredential.getPrivateKey();

    X500NameBuilder subjectBuilder = new X500NameBuilder();
    if (StringUtils.hasText(issuerPublicCert.getCountry())) {
        subjectBuilder.addRDN(BCStyle.C, issuerPublicCert.getCountry());
    }
    if (StringUtils.hasText(issuerPublicCert.getLocation())) {
        subjectBuilder.addRDN(BCStyle.L, issuerPublicCert.getLocation());
    }
    if (StringUtils.hasText(issuerPublicCert.getOrganization())) {
        subjectBuilder.addRDN(BCStyle.O, issuerPublicCert.getOrganization());
    }
    if (StringUtils.hasText(issuerPublicCert.getOrgUnit())) {
        subjectBuilder.addRDN(BCStyle.OU, issuerPublicCert.getOrgUnit());
    }
    subjectBuilder.addRDN(BCStyle.OU, TDMX_DOMAIN_CA_OU);
    subjectBuilder.addRDN(BCStyle.CN, req.getDomainName());
    X500Name subject = subjectBuilder.build();
    X500Name issuer = issuerPublicCert.getSubjectName();
    JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(issuer, new BigInteger("1"),
            req.getNotBefore().getTime(), req.getNotAfter().getTime(), subject, publicKey);

    try {
        BasicConstraints cA = new BasicConstraints(0);
        certBuilder.addExtension(Extension.basicConstraints, true, cA);

        JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
        certBuilder.addExtension(Extension.authorityKeyIdentifier, false,
                extUtils.createAuthorityKeyIdentifier(issuerPublicKey));
        certBuilder.addExtension(Extension.subjectKeyIdentifier, false,
                extUtils.createSubjectKeyIdentifier(publicKey));

        KeyUsage ku = new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign);
        certBuilder.addExtension(Extension.keyUsage, false, ku);

        // RFC5280 http://tools.ietf.org/html/rfc5280#section-4.2.1.10
        // The CA has a CN which is not part of the name constraint - but we can constrain
        // any domain certificate issued to be limited to some OU under the O.
        X500NameBuilder subjectConstraintBuilder = new X500NameBuilder();
        if (StringUtils.hasText(issuerPublicCert.getCountry())) {
            subjectConstraintBuilder.addRDN(BCStyle.C, issuerPublicCert.getCountry());
        }
        if (StringUtils.hasText(issuerPublicCert.getLocation())) {
            subjectConstraintBuilder.addRDN(BCStyle.L, issuerPublicCert.getLocation());
        }
        if (StringUtils.hasText(issuerPublicCert.getOrganization())) {
            subjectConstraintBuilder.addRDN(BCStyle.O, issuerPublicCert.getOrganization());
        }
        if (StringUtils.hasText(issuerPublicCert.getOrgUnit())) {
            subjectConstraintBuilder.addRDN(BCStyle.OU, issuerPublicCert.getOrgUnit());
        }
        subjectConstraintBuilder.addRDN(BCStyle.OU, TDMX_DOMAIN_CA_OU);
        subjectConstraintBuilder.addRDN(BCStyle.OU, req.getDomainName());
        X500Name nameConstraint = subjectConstraintBuilder.build();

        GeneralName snc = new GeneralName(GeneralName.directoryName, nameConstraint);
        GeneralSubtree snSubtree = new GeneralSubtree(snc, new BigInteger("0"), null);
        NameConstraints nc = new NameConstraints(new GeneralSubtree[] { snSubtree }, null);
        certBuilder.addExtension(Extension.nameConstraints, true, nc);

        certBuilder.addExtension(TdmxZoneInfo.tdmxZoneInfo, false, issuerPublicCert.getTdmxZoneInfo());

        ContentSigner signer = SignatureAlgorithm.getContentSigner(issuerPrivateKey,
                req.getSignatureAlgorithm());
        byte[] certBytes = certBuilder.build(signer).getEncoded();

        PKIXCertificate c = CertificateIOUtils.decodeX509(certBytes);

        return new PKIXCredential(c, issuerCredential.getCertificateChain(), privateKey);
    } catch (CertIOException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    } catch (NoSuchAlgorithmException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    } catch (IOException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    }
}

From source file:org.tdmx.client.crypto.certificate.CredentialUtils.java

License:Open Source License

public static PKIXCredential createUserCredential(UserCredentialSpecifier req)
        throws CryptoCertificateException {
    KeyPair kp = null;//from  w  w  w .  ja  v  a 2  s. c o m
    try {
        kp = req.getKeyAlgorithm().generateNewKeyPair();
    } catch (CryptoException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_KEYPAIR_GENERATION, e);
    }

    PublicKey publicKey = kp.getPublic();
    PrivateKey privateKey = kp.getPrivate();

    PKIXCredential issuerCredential = req.getDomainAdministratorCredential();
    PKIXCertificate issuerPublicCert = issuerCredential.getPublicCert();
    PublicKey issuerPublicKey = issuerPublicCert.getCertificate().getPublicKey();
    PrivateKey issuerPrivateKey = issuerCredential.getPrivateKey();

    X500NameBuilder subjectBuilder = new X500NameBuilder();
    if (StringUtils.hasText(issuerPublicCert.getCountry())) {
        subjectBuilder.addRDN(BCStyle.C, issuerPublicCert.getCountry());
    }
    if (StringUtils.hasText(issuerPublicCert.getLocation())) {
        subjectBuilder.addRDN(BCStyle.L, issuerPublicCert.getLocation());
    }
    if (StringUtils.hasText(issuerPublicCert.getOrganization())) {
        subjectBuilder.addRDN(BCStyle.O, issuerPublicCert.getOrganization());
    }
    if (StringUtils.hasText(issuerPublicCert.getOrgUnit())) {
        subjectBuilder.addRDN(BCStyle.OU, issuerPublicCert.getOrgUnit());
    }
    subjectBuilder.addRDN(BCStyle.OU, TDMX_DOMAIN_CA_OU);
    subjectBuilder.addRDN(BCStyle.OU, issuerPublicCert.getCommonName());
    subjectBuilder.addRDN(BCStyle.CN, req.getName());
    X500Name subject = subjectBuilder.build();
    X500Name issuer = issuerPublicCert.getSubjectName();
    JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(issuer, new BigInteger("1"),
            req.getNotBefore().getTime(), req.getNotAfter().getTime(), subject, publicKey);

    try {
        JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
        certBuilder.addExtension(Extension.authorityKeyIdentifier, false,
                extUtils.createAuthorityKeyIdentifier(issuerPublicKey));
        certBuilder.addExtension(Extension.subjectKeyIdentifier, false,
                extUtils.createSubjectKeyIdentifier(publicKey));

        KeyUsage ku = new KeyUsage(
                KeyUsage.digitalSignature | KeyUsage.nonRepudiation | KeyUsage.keyEncipherment);
        certBuilder.addExtension(Extension.keyUsage, false, ku);

        certBuilder.addExtension(TdmxZoneInfo.tdmxZoneInfo, false, issuerPublicCert.getTdmxZoneInfo());

        ContentSigner signer = SignatureAlgorithm.getContentSigner(issuerPrivateKey,
                req.getSignatureAlgorithm());
        byte[] certBytes = certBuilder.build(signer).getEncoded();

        PKIXCertificate c = CertificateIOUtils.decodeX509(certBytes);

        return new PKIXCredential(c, issuerCredential.getCertificateChain(), privateKey);
    } catch (CertIOException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    } catch (NoSuchAlgorithmException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    } catch (IOException e) {
        throw new CryptoCertificateException(CertificateResultCode.ERROR_CA_CERT_GENERATION, e);
    }
}

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

License:Open Source License

/** 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 w w w .j a v  a2s. 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

License:Open Source License

/** 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   www  . java 2s.  c  o  m*/
 *
 * @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;
}

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

License:Open Source License

/** Generates a self-signed certificate to use as a CA root certificate.
 *
 * @param keyPair the root public/private key pair
 * @return a self-signed CA root certificate
 *
 * @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
 *//*  ww  w. ja  v a 2s.  com*/
protected static X509Certificate generateRootX509Certificate(final KeyPair keyPair)
        throws CertificateEncodingException, NoSuchProviderException, NoSuchAlgorithmException,
        SignatureException, InvalidKeyException, IOException {
    //Preconditions
    assert keyPair != null : "keyPair must not be null";

    final UUID rootUUID = UUID.randomUUID();
    // provide items to X500Principal in reverse order
    final X500Principal rootX500Principal = new X500Principal(
            "UID=" + rootUUID + ", O=Texai Certification Authority, CN=texai.org");
    final X500Name subject = new X500Name(rootX500Principal.getName());
    final X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(
            new X500Name(rootX500Principal.getName()), // issuer,
            getNextSerialNumber(), // serial
            new Date(System.currentTimeMillis() - 10000L), // notBefore,
            new Date(System.currentTimeMillis() + VALIDITY_PERIOD), // notAfter,
            subject, new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic().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 subject key identifier
    x509v3CertificateBuilder.addExtension(Extension.subjectKeyIdentifier, false, // isCritical
            jcaX509ExtensionUtils.createSubjectKeyIdentifier(keyPair.getPublic()));

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

    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);

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

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

    //Postconditions
    try {
        rootX509Certificate.checkValidity();
        rootX509Certificate.verify(keyPair.getPublic());

        return rootX509Certificate;
    } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException | SignatureException
            | CertificateException ex) {
        throw new TexaiException(ex);
    }
}