0

java.security.KeyStore uses KeyStoreSpi implementations to provide keystores of different types. Basic OpenJDK comes with support of JKS, JCEKS and PKCS12 keystore types. The first two implement proprietary Sun/Oracle format and PKCS12 is a public standard.

I know that JCEKS does support symmetric keys and PKCS12 does not. Which other KeyStoreSpi implementations (like Bouncy Castle) provide support of symmetric keys? It looks like devs like to hide such info. E.g. Bouncy Castle docs only mentions:

The fourth is the BCFKS key store which is a FIPS compliant key store which is also designed for general key storage and based on ASN.1. This key store type is encrypted and supports the use of SCRYPT and the storage of some symmetric key types.

Evan
  • 649
  • 1
  • 9
  • 22

1 Answers1

1

Why do you think that a PKCS#12 keystore does not save secret keys in general? I'm working on Desktop OpenJDK 11.x and I do not have any problem in saving and reloading of a secret key with a PKCS#12 keystore.

But you are right - there are some Java implementations where this won't work - just give it a try!

output:

Keystore Type PKCS12
source: https://www.pixelstech.net/article/1420427307-Different-types-of-keystore-in-Java----PKCS12
create a keystore
load the keystore and store a secret key
key after generation length: 32 data: eb6b8efafcee46880ea75b83754442efe4ee9d66ce755698cc803fd7775e4e78
load secret key from keystore
key after loading    length: 32 data: eb6b8efafcee46880ea75b83754442efe4ee9d66ce755698cc803fd7775e4e78

Security warning: the code does not have any exception handling and is for educational purpose only.

code:

import javax.crypto.KeyGenerator;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.KeyStore;

public class KeystoreTypePKCS12 {
    public static void main(String[] args) {
        System.out.println("Keystore Type PKCS12");
        // https://stackoverflow.com/questions/64677544/which-keystore-implementations-can-be-used-for-storing-symmetric-keys
        System.out.println("source: https://www.pixelstech.net/article/1420427307-Different-types-of-keystore-in-Java----PKCS12");

        System.out.println("create a keystore");
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(null, null);
            keyStore.store(new FileOutputStream("keystore.p12"), "password".toCharArray());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        System.out.println("load the keystore and store a secret key");
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(new FileInputStream("keystore.p12"), "password".toCharArray());
            // generate an aes secret key
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(256);
            Key key = keyGen.generateKey();
            System.out.println("key after generation length: " + key.getEncoded().length
                    + " data: " + bytesToHex(key.getEncoded()));
            // store it in the keystore
            keyStore.setKeyEntry("secret", key, "password".toCharArray(), null);
            // save the keystore
            keyStore.store(new FileOutputStream("keystore.p12"), "password".toCharArray());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        System.out.println("load secret key from keystore");
        try{
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(new FileInputStream("keystore.p12"), "password".toCharArray());
            Key keyLoad = keyStore.getKey("secret", "password".toCharArray());
            System.out.println("key after loading    length: " + keyLoad.getEncoded().length
                    + " data: " + bytesToHex(keyLoad.getEncoded()));
        } catch (Exception ex){
            ex.printStackTrace();
        }

    }
    private static String bytesToHex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        return result.toString();
    }
}
Michael Fehr
  • 5,827
  • 2
  • 19
  • 40
  • 1
    Interesting, I did some unit tests and it appears you're correct and PKCS12 is able to store at least AES keys. I'm using ChaCha20 and PKCS12 fails with `Key protection algorithm not found: unrecognized algorithm name: ChaCha20`. In opposite, JCEKS can store both AES and ChaCha20 keys. Still, symmetric key is basically just a byte array, don't understand why keystores should be so picky. – Evan Nov 04 '20 at 11:44
  • I'm glad to read that your tests run successfully. Could you kindly mark my answer as "accepted" - thanks? – Michael Fehr Nov 06 '20 at 09:30