public static synchronized X509Certificate createX509V3Certificate(KeyPair kp, int days, X500NameBuilder issuerBuilder,
            X500NameBuilder subjectBuilder, String domain, String signAlgoritm, Set<String> sanDnsNames ) throws GeneralSecurityException, IOException {
        PublicKey pubKey = kp.getPublic();
        PrivateKey privKey = kp.getPrivate();

        byte[] serno = new byte[8];
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed((new Date().getTime()));
        random.nextBytes(serno);
        BigInteger serial = (new java.math.BigInteger(serno)).abs();

        X500Name issuerDN = issuerBuilder.build();
        X500Name subjectDN = subjectBuilder.build();

        // builder
        JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( //
                issuerDN, //
                serial, //
                new Date(), //
                new Date(System.currentTimeMillis() + days * (1000L * 60 * 60 * 24)), //
                subjectDN, //
                pubKey //
                );

        // add subjectAlternativeName extension that includes all relevant names.
        final GeneralNames subjectAlternativeNames = getSubjectAlternativeNames( sanDnsNames );

        final boolean critical = subjectDN.getRDNs().length == 0;
        certBuilder.addExtension(Extension.subjectAlternativeName, critical, subjectAlternativeNames);

        // add keyIdentifiers extensions
        JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
        certBuilder.addExtension(Extension.subjectKeyIdentifier, false, utils.createSubjectKeyIdentifier(pubKey));
        certBuilder.addExtension(Extension.authorityKeyIdentifier, false, utils.createAuthorityKeyIdentifier(pubKey));

        try {
            // build the certificate
            ContentSigner signer = new JcaContentSignerBuilder(signAlgoritm).build(privKey);
            X509CertificateHolder cert = certBuilder.build(signer);

            // verify the validity
            if (!cert.isValidOn(new Date())) {
                throw new GeneralSecurityException("Certificate validity not valid");
            }

            // verify the signature (self-signed)
            ContentVerifierProvider verifierProvider = new JcaContentVerifierProviderBuilder().build(pubKey);
            if (!cert.isSignatureValid(verifierProvider)) {
                throw new GeneralSecurityException("Certificate signature not valid");
            }

            return new JcaX509CertificateConverter().getCertificate(cert);

        } catch (OperatorCreationException | CertException e) {
            throw new GeneralSecurityException(e);
        }
    }
Creates an X509 version3 certificate.

@param kp           KeyPair that keeps the public and private keys for the new certificate.
@param days       time to live
@param issuerBuilder     IssuerDN builder
@param subjectBuilder    SubjectDN builder
@param domain       Domain of the server.
@param signAlgoritm Signature algorithm. This can be either a name or an OID.
@return X509 V3 Certificate
@throws GeneralSecurityException if there was a problem creating the certificate
@throws IOException if there was a problem creating the certificate
xmppserver/src/main/java/org/jivesoftware/util/CertificateManager.java