【问题标题】:Which KeyStore implementations can be used for storing symmetric keys?哪些 KeyStore 实现可用于存储对称密钥?
【发布时间】:2020-11-04 09:40:39
【问题描述】:

java.security.KeyStore 使用KeyStoreSpi 实现来提供不同类型的密钥库。 Basic OpenJDK 支持 JKS、JCEKS 和 PKCS12 密钥库类型。前两个实现专有的 Sun/Oracle 格式,PKCS12 是公共标准。

我知道 JCEKS 确实支持对称密钥,而 PKCS12 不支持。哪些其他KeyStoreSpi 实现(如Bouncy Castle)提供对称密钥支持?看起来开发人员喜欢隐藏此类信息。例如。充气城堡docs 仅提及:

第四个是 BCFKS 密钥库,它是符合 FIPS 的密钥库 它也是为通用密钥存储而设计的,基于 ASN.1。 此密钥存储类型已加密并支持使用 SCRYPT 和 一些对称密钥类型的存储。

【问题讨论】:

    标签: java keystore symmetric-key


    【解决方案1】:

    为什么您认为 PKCS#12 密钥库通常不保存密钥?我正在使用 Desktop OpenJDK 11.x,使用 PKCS#12 密钥库保存和重新加载密钥没有任何问题。

    但你是对的 - 在某些 Java 实现中这不起作用 - 试试吧!

    输出:

    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
    

    安全警告:代码没有任何异常处理,仅用于教育目的。

    代码:

    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://*.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();
        }
    }
    

    【讨论】:

    • 有趣,我做了一些单元测试,看来你是正确的,PKCS12 至少能够存储 AES 密钥。我正在使用 ChaCha20 和 PKCS12 失败,Key protection algorithm not found: unrecognized algorithm name: ChaCha20。相反,JCEKS 可以同时存储 AES 和 ChaCha20 密钥。尽管如此,对称密钥基本上只是一个字节数组,不明白为什么密钥库要这么挑剔。
    • 很高兴得知您的测试运行成功。您能否将我的回答标记为“已接受”-谢谢?