private static String[] generate(String fqdn, KeyPair keypair, Random random,
                                     Date notBefore, Date notAfter, String algorithm) throws Exception {

        final PrivateKey key = keypair.getPrivate();

        // Prepare the information required for generating an X.509 certificate.
        final X500Name owner = new X500Name("CN=" + fqdn);
        final X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
                owner, new BigInteger(64, random), notBefore, notAfter, owner, keypair.getPublic());

        final List<GeneralName> names = new ArrayList<>();
        // Add fqdn as Subject Alternative Name too for clients that don't use CN when validating such as
        // OkHttp.
        if (NetUtil.isValidIpV4Address(fqdn) || NetUtil.isValidIpV6Address(fqdn)) {
            names.add(new GeneralName(iPAddress, fqdn));
        } else {
            names.add(new GeneralName(dNSName, fqdn));
        }

        // Support request with IP or domain for local connections.
        if ("localhost".equals(fqdn)) {
            names.add(new GeneralName(iPAddress, "127.0.0.1"));
            names.add(new GeneralName(iPAddress, "::1"));
        } else if ("127.0.0.1".equals(fqdn)) {
            names.add(new GeneralName(dNSName, "localhost"));
            names.add(new GeneralName(iPAddress, "::1"));
        }

        builder.addExtension(subjectAlternativeName,
                             false,
                             new GeneralNames(names.toArray(new GeneralName[0])));

        final ContentSigner signer = new JcaContentSignerBuilder(
                "EC".equalsIgnoreCase(algorithm) ? "SHA256withECDSA" : "SHA256WithRSAEncryption").build(key);
        final X509CertificateHolder certHolder = builder.build(signer);
        final X509Certificate cert =
                new JcaX509CertificateConverter().setProvider(bouncyCastleProvider).getCertificate(certHolder);
        cert.verify(keypair.getPublic());

        // Encode the private key into a file.
        ByteBuf wrappedBuf = Unpooled.wrappedBuffer(key.getEncoded());
        ByteBuf encodedBuf;
        final String keyText;
        try {
            encodedBuf = Base64.encode(wrappedBuf, true);
            try {
                keyText = "-----BEGIN PRIVATE KEY-----\n" +
                          encodedBuf.toString(CharsetUtil.US_ASCII) +
                          "\n-----END PRIVATE KEY-----\n";
            } finally {
                encodedBuf.release();
            }
        } finally {
            wrappedBuf.release();
        }

        // Change all asterisk to 'x' for file name safety.
        fqdn = fqdn.replaceAll("[^\\w.-]", "x");

        final File keyFile = PlatformDependent.createTempFile("keyutil_" + fqdn + '_', ".key", null);
        keyFile.deleteOnExit();

        OutputStream keyOut = new FileOutputStream(keyFile);
        try {
            keyOut.write(keyText.getBytes(CharsetUtil.US_ASCII));
            keyOut.close();
            keyOut = null;
        } finally {
            if (keyOut != null) {
                safeClose(keyFile, keyOut);
                safeDelete(keyFile);
            }
        }

        wrappedBuf = Unpooled.wrappedBuffer(cert.getEncoded());
        final String certText;
        try {
            encodedBuf = Base64.encode(wrappedBuf, true);
            try {
                // Encode the certificate into a CRT file.
                certText = "-----BEGIN CERTIFICATE-----\n" +
                           encodedBuf.toString(CharsetUtil.US_ASCII) +
                           "\n-----END CERTIFICATE-----\n";
            } finally {
                encodedBuf.release();
            }
        } finally {
            wrappedBuf.release();
        }

        final File certFile = PlatformDependent.createTempFile("keyutil_" + fqdn + '_', ".crt", null);
        certFile.deleteOnExit();

        OutputStream certOut = new FileOutputStream(certFile);
        try {
            certOut.write(certText.getBytes(CharsetUtil.US_ASCII));
            certOut.close();
            certOut = null;
        } finally {
            if (certOut != null) {
                safeClose(certFile, certOut);
                safeDelete(certFile);
                safeDelete(keyFile);
            }
        }

        return new String[] { certFile.getPath(), keyFile.getPath() };
    }
Deletes the generated X.509 certificate file and RSA private key file.
core/src/main/java/com/linecorp/armeria/internal/common/util/SelfSignedCertificate.java