Reputation: 714
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.
Upvotes: 0
Views: 1651
Reputation: 6394
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);
try (FileOutputStream outStream = new FileOutputStream("keystore.p12") {
keyStore.store(outStream, "password".toCharArray());
}
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("load the keystore and store a secret key");
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream inStream = new FileInputStream("keystore.p12")) {
keyStore.load(inStream, "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
try (FileOutputStream outStream = new FileOutputStream("keystore.p12")) {
keyStore.store(outStream, "password".toCharArray());
}
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("load secret key from keystore");
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream inStream = new FileInputStream("keystore.p12")) {
keyStore.load(inputStream, "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) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
return result.toString();
}
}
Upvotes: 1