Camilo Salazar Camilo Salazar - 1 month ago 27
Java Question

Is it possible to store secret keys on SoftHSM?

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

Answer

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)