如何从Java的KeyStore中检索实际的密钥?

问题描述 投票:-1回答:1

我对Java KeyStore不太了解。我想要做的是具有一个加密的结构来存储我的密钥。

我有多个集群,每个集群都有一个密钥,现在我想安全地存储这些密钥,以便使用单个主密钥(例如,'loginid')对它们进行加密]

我在这个问题上徘徊了很多,在stackoverflow上的某个地方,有人建议使用Java keyStore来存储SecretKey(对称加密)。我阅读了它的文档,发现它完全符合我的要求,但无法正确理解其实现。

这是我正在处理的代码段-


public class Prac {

    public static void main(String[] args) throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, UnrecoverableEntryException {
        KeyStore ks = KeyStore.getInstance("JCEKS");        
        char[] ksPwd = "yashkaranje98".toCharArray();        
        ks.load(null, ksPwd);        
        KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(ksPwd);

        javax.crypto.SecretKey mySecretKey = new SecretKeySpec("_anky!@ubn#$0e41".getBytes(),"AES");
        KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey);
        ks.setEntry("cluster1", skEntry, protParam);

        java.io.FileOutputStream fos = null;
        try {
            fos = new java.io.FileOutputStream("keystore.ks");
            ks.store(fos, ksPwd);
        } finally {
            if (fos != null) {
                fos.close();
            }
        }

        java.io.FileInputStream fis = null;
        try {
          ks.load(new FileInputStream("keystore.ks"), ksPwd);
        } finally {
                if (fis != null) {
                        fis.close();
                }
        }


        SecretKey key = (SecretKey)ks.getKey("cluster1", ksPwd);
        String encodedKey = Base64.getEncoder().encodeToString(key.getEncoded());
        System.out.println(encodedKey);  

    }
}

别名:“ cluster1”

存储密钥:_anky!@ ubn#$ 0e41

保护参数:yashkaranje98

它打印:X2Fua3khQHVibiMkMGU0MQ ==

我期望的是关键因素:_anky!@ ubn#$ 0e41

请先让我知道我所缺少的...但是在告诉我我所期望的是合法的之前吗?还是有意义?

((我仍在学习这个KeyStore概念,因此可能会有一些愚蠢的错误。)

java encryption cryptography keystore secret-key
1个回答
0
投票

秘密AES密钥由随机字节组成。应该直接打印这样的键,因为这些字节可能无法表示有效字符,或者它们可能会显示不打印在屏幕上的控制字符。如果要复制它们,则可能会丢失数据。如果在错误的终端上打印它们,则可能会发送终端控制代码。因此,

需要

将十六进制或基数为64的键值打印出来。通常对于对称键,最好使用十六进制,因为很容易从十六进制中看到内容和大小(字节是十六进制大小的一半,以位为单位的大小是十六进制大小的4倍,因为每个十六进制数字代表4位半字节。但是,由于Java仍然缺少好的Hex编码器,因此base 64也是不错的选择。当然,在这种情况下,为了进行比较,在将其插入密钥存储区之前,还应该从base 64对其进行解码。


还请注意,当您在字符串上调用getBytes时,未指定字符编码。如果您使用更高价值的字符,那么在各种系统上可能会得到不同的结果,因为不带参数的getBytes假定平台编码。通常指定StandardCharsets.UTF_8更有意义。

当然,因为键应该包含随机字节,所以getBytes方法需要完全使用,但是无论如何,您都应牢记这一点。


[当我看代码时,您似乎错过了Java的最近十年。没有var,没有null避免,缺少导入,也没有尝试资源。真可惜,因为那样会使您的代码更具可读性。请注意,这是有效的,但是是的...
© www.soinside.com 2019 - 2024. All rights reserved.