I've found this thread: Connecting to SoftHSM java and it works when storing private keys, just like the example.
But I need to store secret keys, such as AES.
Here's my code:
import java.security.*;
import sun.security.pkcs11.*;
import javax.crypto.spec.SecretKeySpec;
public class Main {
public static void main(String[] args) throws Exception {
// Set up the Sun PKCS 11 provider
String configName = "softhsm.cfg";
Provider p = new SunPKCS11(configName);
if (-1 == Security.addProvider(p)) {
throw new RuntimeException("could not add security provider");
}
// Load the key store
char[] pin = "mypin".toCharArray();
KeyStore keyStore = KeyStore.getInstance("PKCS11", p);
keyStore.load(null, pin);
// AES key
SecretKeySpec secretKeySpec = new SecretKeySpec("0123456789ABCDEF".getBytes(), "AES");
Key key = new SecretKeySpec(secretKeySpec.getEncoded(), "AES");
keyStore.setKeyEntry("AA", key, "1234".toCharArray(), null);
keyStore.store(null); //this gives me the exception.
}
}
And this is the softhsm.cfg file:
name = SoftHSM
library = /usr/local/lib/softhsm/libsofthsm.so
slot = 0
attributes(generate, *, *) = {
CKA_TOKEN = true
}
attributes(generate, CKO_CERTIFICATE, *) = {
CKA_PRIVATE = false
}
attributes(generate, CKO_PUBLIC_KEY, *) = {
CKA_PRIVATE = false
}
When executing keyStore.store(null) I'm getting java.security.KeyStoreException Cannot convert to PKCS11 keys
Turns out the Exception occurs with SoftHSMv1. I installed SoftHSMv2, wich you can get using git to download it from GitHub, and use it to store secret keys. Don't download SoftHSMv2 from the OpenDNSsec website because it won't work!!.
Finally I had to change the softhsm.cfg file to point the new library and for some reason I ignore, SoftHSM2 changes the number of the initializated slot, you can verify it using sudo softhsm2-util --show-slots
softhsm.cfg:
name = SoftHSM
library = /usr/local/lib/softhsm/libsofthsm2.so
slot = 498488451
attributes(generate, *, *) = {
CKA_TOKEN = true
}
attributes(generate, CKO_CERTIFICATE, *) = {
CKA_PRIVATE = false
}
attributes(generate, CKO_PUBLIC_KEY, *) = {
CKA_PRIVATE = false
}
My code:
import java.security.*;
import sun.security.pkcs11.*;
import javax.crypto.spec.SecretKeySpec;
public class Main {
public static void main(String[] args) throws Exception {
// Set up the Sun PKCS 11 provider
String configName = "softhsm.cfg";
Provider p = new SunPKCS11(configName);
if (-1 == Security.addProvider(p)) {
throw new RuntimeException("could not add security provider");
}
// Load the key store
char[] pin = "mypin".toCharArray();
KeyStore keyStore = KeyStore.getInstance("PKCS11", p);
keyStore.load(null, pin);
// AES key
SecretKeySpec secretKeySpec = new SecretKeySpec("0123456789ABCDEF".getBytes(), "AES");
Key key = new SecretKeySpec(secretKeySpec.getEncoded(), "AES");
keyStore.setKeyEntry("AA", key, "1234".toCharArray(), null);
keyStore.store(null); //this no longer gives me the exception.
Enumeration<String> aliases = keyStore.aliases();
while(aliases.hasMoreElements()){
String alias = aliases.nextElement();
System.out.println(alias + ": " + keyStore.getKey(alias,"1234".toCharArray()));
}
}
}
Which gives me the output:
AA: SunPKCS11-SoftHSM AES secret key, 16 bits (id 2, token object, not sensitive, unextractable)
If you try to get the key using something like keyStore.getKey("AA", "1234".toCharArray());
you'll get an objet with some attributes of the key but you wont be able to use .getEncoded()
to actually get the key itself since it is unextractable.