The CA signing private key can be secured using PKCS11 keystore  for providing extra level of security. This blog will provide steps to import key into pkcs11 keystore and signs the pkcs10 request in java. 

Import keys into pkcs11 keystore

Create pkcs12 keystore with key and certificate.

openssl pkcs12 -export -in <ca cert> -inkey <ca key> -out castore.p12

Import to pkcs11 keystore.

keytool -importkeystore -deststorepass <dest passwd> -destkeystore NONE -srckeystore castore.p12 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /home/test/pkcs11.cfg -deststoretype PKCS11 -srcstoretype PKCS12 -srcstorepass <src passwd> -alias casignkey

Add the SunPKCS11 provider

String configName = "/home/test/pkcs11.cfg";

Provider p = new SunPKCS11(configName);

Security.addProvider(p);

Load the keys to keystore

char[] pin = "<keystore pin>".toCharArray();

KeyStore keyStore = KeyStore.getInstance("PKCS11", p);

keyStore.load(null, pin);

Get the CA private key

PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore.getEntry("casignkey", null);

PrivateKey privateKey = privateKeyEntry.getPrivateKey();

 Load the csr into PKCS10 object

File csrf = new File("/test-key/test.csr");

Reader pemcsr = new FileReader(csrf);

PemReader reader = new PemReader(pemcsr);   

PemObject pem = reader.readPemObject();

PKCS10CertificationRequest csr = new PKCS10CertificationRequest(pem.getContent());

Build an issuer using X500Name builder

 X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE);

 x500NameBld.addRDN(BCStyle.C, "<country>");

x500NameBld.addRDN(BCStyle.ST, "<street>");

x500NameBld.addRDN(BCStyle.L, "<location>");

x500NameBld.addRDN(BCStyle.O, "<Origin>");

x500NameBld.addRDN(BCStyle.CN, "<Test Req>");

X500Name issuer = x500NameBld.build();

Create X509v3 certificate builder object with extensions

        X509v3CertificateBuilder xcb = new X509v3CertificateBuilder(issuer, bi, start, end, csr.getSubject(), csr.getSubjectPublicKeyInfo());

        JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();

xcb  .addExtension(Extension.basicConstraints, false,

         new BasicConstraints(false)) .addExtension(Extension.keyUsage, true,

         new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment)).addExtension(Extension.extendedKeyUsage,

         true, new ExtendedKeyUsage(ASN_WebUsage))

                 .addExtension(Extension.authorityKeyIdentifier,false, extUtils.createAuthorityKeyIdentifier(caCert)).addExtension(Extension.subjectKeyIdentifier,  

                 false, extUtils.createSubjectKeyIdentifier(caCert.getPublicKey()));

Create content signer with private key

ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSA").setProvider("SunPKCS11-pkcs11Test").build(privateKey);

Sign and retrieve the certificate

x509 = new JcaX509CertificateConverter().getCertificate(xcb.build(sigGen));

  • No labels