Signing CSR using key stored in PKCS11 softhsm keystore
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));