package me.hatter.tests.ca; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.cert.X509Certificate; import java.util.Date; import me.hatter.tools.commons.bytes.Bytes; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; // https://github.com/bcgit/bc-java/blob/master/misc/src/main/java/org/bouncycastle/jcajce/examples/PKCS12Example.java public class BCECCATest { static { Security.addProvider(new BouncyCastleProvider()); } static String ROOT = "C=CN, O=Hatter, CN=Hatter EC Root CA"; static String INTERMEDIATE = "C=CN, O=Hatter, CN=Hatter EC Intermediate CA"; static String SERVER = "C=CN, O=Hatter, CN=example.com"; public static X509Certificate createMasterCert(PublicKey pubKey, PrivateKey privKey) throws Exception { X509v3CertificateBuilder v3Bldr = new JcaX509v3CertificateBuilder(new X500Name(ROOT), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30)), new X500Name(ROOT), pubKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); v3Bldr.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign)); v3Bldr.addExtension(Extension.basicConstraints, true, new BasicConstraints(true)); v3Bldr.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(pubKey)); v3Bldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(pubKey)); X509CertificateHolder certHldr = v3Bldr.build(new JcaContentSignerBuilder("SHA256WithECDSA").setProvider("BC").build(privKey)); X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHldr); cert.checkValidity(new Date()); cert.verify(pubKey); return cert; } public static X509Certificate createIntermediateCert(PublicKey pubKey, PrivateKey caPrivKey, X509Certificate caCert) throws Exception { X509v3CertificateBuilder v3Bldr = new JcaX509v3CertificateBuilder(caCert, BigInteger.valueOf(2), new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30)), new X500Name(INTERMEDIATE), pubKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); v3Bldr.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign)); v3Bldr.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(pubKey)); v3Bldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(caCert.getPublicKey())); v3Bldr.addExtension(Extension.basicConstraints, true, new BasicConstraints(0)); X509CertificateHolder certHldr = v3Bldr.build(new JcaContentSignerBuilder("SHA256WithECDSA").setProvider("BC").build(caPrivKey)); X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHldr); cert.checkValidity(new Date()); cert.verify(caCert.getPublicKey()); return cert; } public static X509Certificate createCert(PublicKey pubKey, PrivateKey caPrivKey, X509Certificate caCert) throws Exception { X509v3CertificateBuilder v3Bldr = new JcaX509v3CertificateBuilder(caCert, BigInteger.valueOf(3), new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30)), new X500Name(SERVER), pubKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); v3Bldr.addExtension(Extension.basicConstraints, true, new BasicConstraints(false)); ASN1EncodableVector purposes = new ASN1EncodableVector(); purposes.add(KeyPurposeId.id_kp_serverAuth); purposes.add(KeyPurposeId.id_kp_clientAuth); v3Bldr.addExtension(Extension.extendedKeyUsage, false, new DERSequence(purposes)); v3Bldr.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(pubKey)); v3Bldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(caCert.getPublicKey())); v3Bldr.addExtension(Extension.subjectAlternativeName, false, new GeneralNames(new GeneralName[] { new GeneralName(GeneralName.dNSName, "example.com"), new GeneralName(GeneralName.dNSName, "*.example.com") })); X509CertificateHolder certHldr = v3Bldr.build(new JcaContentSignerBuilder("SHA256WithECDSA").setProvider("BC").build(caPrivKey)); X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHldr); cert.checkValidity(new Date()); cert.verify(caCert.getPublicKey()); return cert; } public static void main(String[] args) throws Exception { KeyPair rsaKeyPair = KeyPairGenerator.getInstance("EC").generateKeyPair(); X509Certificate root = createMasterCert(rsaKeyPair.getPublic(), rsaKeyPair.getPrivate()); X509Certificate intermediate = createIntermediateCert(rsaKeyPair.getPublic(), rsaKeyPair.getPrivate(), root); X509Certificate server = createCert(rsaKeyPair.getPublic(), rsaKeyPair.getPrivate(), intermediate); System.out.println(root); System.out.println(intermediate); System.out.println(server); System.out.println("ROOT:"); System.out.println("-----BEGIN CERTIFICATE-----"); System.out.println(Bytes.from(root.getEncoded()).asBase64Splited(64)); System.out.println("-----END CERTIFICATE-----"); System.out.println("INTERMEDIATE:"); System.out.println("-----BEGIN CERTIFICATE-----"); System.out.println(Bytes.from(intermediate.getEncoded()).asBase64Splited(64)); System.out.println("-----END CERTIFICATE-----"); System.out.println("SERVER:"); System.out.println("-----BEGIN CERTIFICATE-----"); System.out.println(Bytes.from(server.getEncoded()).asBase64Splited(64)); System.out.println("-----END CERTIFICATE-----"); } }