1import java.io.FileWriter
2import java.math.BigInteger
3import java.security.KeyPairGenerator
4import java.security.SecureRandom
5import java.security.spec.ECGenParameterSpec
6import java.time.Duration
7import java.time.Instant
8import java.util.Date
9import org.bouncycastle.asn1.x500.X500Name
10import org.bouncycastle.asn1.x509.BasicConstraints
11import org.bouncycastle.asn1.x509.ExtendedKeyUsage
12import org.bouncycastle.asn1.x509.Extension
13import org.bouncycastle.asn1.x509.GeneralName
14import org.bouncycastle.asn1.x509.GeneralNames
15import org.bouncycastle.asn1.x509.KeyPurposeId
16import org.bouncycastle.asn1.x509.KeyUsage
17import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
18import org.bouncycastle.openssl.jcajce.JcaPEMWriter
19import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator
20import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
21
22fun main() {
23 val keys = KeyPairGenerator.getInstance("EC").apply { initialize(ECGenParameterSpec("secp256r1")) }.generateKeyPair()
24 val name = X500Name("CN=localhost")
25 val notBefore = Instant.now()
26
27 val cert = JcaX509v3CertificateBuilder(
28 name, BigInteger(127, SecureRandom()),
29 Date.from(notBefore), Date.from(notBefore.plus(Duration.ofDays(365))),
30 name, keys.public,
31 ).apply {
32 addExtension(
33 Extension.subjectAlternativeName, false,
34 GeneralNames(arrayOf(GeneralName(GeneralName.dNSName, "localhost"), GeneralName(GeneralName.iPAddress, "127.0.0.1"))),
35 )
36 addExtension(Extension.basicConstraints, true, BasicConstraints(false))
37 addExtension(Extension.keyUsage, true, KeyUsage(KeyUsage.digitalSignature))
38 addExtension(Extension.extendedKeyUsage, false, ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth))
39 }.build(JcaContentSignerBuilder("SHA256withECDSA").build(keys.private))
40
41 JcaPEMWriter(FileWriter("cert.pem")).use { it.writeObject(cert) }
42 JcaPEMWriter(FileWriter("key.pem")).use { it.writeObject(JcaPKCS8Generator(keys.private, null)) }
43}