I am seeing an null pointer exception when trying to get the private key from java pkcs11 keystore, when the key is generated by pkcs11-tool. This works fine if the key is generate using keytool. I can list the keys from pkcs11-tool as well but not from keytool. What is the correct way to import or generate keys other than keytool so that they are visible to java pkcs11 keystore?
Generate keys:
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so -l --pin <pin> --keypairgen --key-type rsa:2048 --label jtest
From java load and access the key(code snippet):
String configName = "/tmp/pkcs11.cfg";
Provider p = new SunPKCS11(configName);
Security.addProvider(p);
char[] pin = "<pin>".toCharArray();
KeyStore keyStore = KeyStore.getInstance("PKCS11", p);
keyStore.load(null, pin);
PrivateKeyEntry privateKeyEntry =
(PrivateKeyEntry)keyStore.getEntry("jtest", null);
PrivateKey privateKey = privateKeyEntry.getPrivateKey();
See the exception when trying to get the private key above.
Keytool automatically generates a self-signed certificate when it generates a key entry, whereas PKCS#11 allows to create a key pair without a corresponding certificate.
The Java keystore API simply ignores key pair entries without a certificate. That's why keytool -list ...
does not show the entry when it was created with pkcs11-tool
. If you take a look at the Oracle PKCS#11 guide and especially the restrictions, it says:
Once a private key and certificate have been matched (and its certificate chain built), the information is stored in a private key entry with the CKA_LABEL value from end entity certificate as the KeyStore alias.
...
Any private key or certificate object not part of a private key entry or trusted certificate entry is ignored.
Therefore, when you call keyStore.getEntry("jtest", null);
it does not find a matching key entry, which causes the NPE in the following line.