private static X509Certificate generateSelfSignedCertificate(KeyPair keyPair,
                                                                 String subjectCn,
                                                                 int validityDays) 
            throws OperatorCreationException, CertificateException {

        // Valid from now until now + validityDays
        long now = System.currentTimeMillis();
        Date notBefore = new Date(now);
        Date notAfter  = new Date(now + validityDays * 24L * 60L * 60L * 1000L);

        // Use current time (millis) as the serial number
        BigInteger serialNumber = BigInteger.valueOf(now);

        X500Name dnName = new X500Name("CN=" + subjectCn);

        // Build the certificate (Subject = Issuer = dnName)
        X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
                dnName,                  // issuer
                serialNumber,            // serial
                notBefore,               // valid from
                notAfter,                // valid to
                dnName,                  // subject
                keyPair.getPublic()      // public key
        );

        // Sign with private key (SHA256withRSA)
        ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA")
                .setProvider("BC")
                .build(keyPair.getPrivate());

        // Convert to a standard Java X509Certificate
        return new JcaX509CertificateConverter()
                .setProvider("BC")
                .getCertificate(certBuilder.build(signer));
    }
Creates a self-signed certificate, valid for 'validityDays' days,
with Subject and Issuer = "CN=<subjectCn>".
integration/logstash-plugins/logstash-output-vespa/src/main/java/org/logstashplugins/SelfSignedCertGenerator.java