如何在 Java 中生成 384 位对称密钥大小?

How to generate a 384-bit Symmetric Key Size in Java?

我正在研究采用比 256 位(即 384)更大的对称密钥大小的密码?有没有一种方法可以使用 384 位的 KDF(或与此相关的任何其他东西)生成对称密钥。我尝试在 java 中使用 Key Generator 并使用 keyGenerator.init(384) 但它最多只支持 256 位。您认为我可以将 128 位对称密钥与从 Java 中的密钥生成器生成的 256 位对称密钥结合起来吗?我想避免必须尝试使用​​散列函数、对其进行大量迭代并尝试向其中添加我自己的随机盐。我知道这是一个不常见的问题,因为没有人会寻找 384 位对称密钥大小。我不是特别在寻找 KDF,只是一种生成随机对称密钥的简单而强大的方法。我的用例不涉及获取诸如用户密码之类的低熵值并将其作为密钥。

为什么不使用 SecretKeyFactory class 和 PBKDF2WithHmacSHA384 算法。您可以在文档 here and here.

中找到详细信息

代码如下所示:

SecureRandom random = SecureRandom.getInstanceStrong();
byte[] salt = new byte[32];
random.nextBytes(salt);
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, 
   keyLength);
SecretKeyFactory keyFactory = 
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA384");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
    "AES");

最好在使用后清除 SecretKeySpecSecretKey,以避免将密钥暴露在堆转储中。从 Java 8 开始,没有简单的方法可以做到这一点,因为这两个接口的实现似乎没有实现接口 Destroyable 的方法 destroy()。所以使用后用反射清除它们。

Do you think I could combine a 128-bit symmetric key with a 256 bit one generated from Key Generator in Java?

当然,对于 256 位和 128 位密钥,您只需使用 getEncoded() 检索字节,使用 Arrays.concat 将返回的两个 byte[] 合并为一个 byte[],然后对结果使用 new SecretKeySpec

I'd want to avoid having to try to use a hashing function, iterating it a lot, and trying to add my own random salts to it.

如果您有 256 位源 material,那么您可以使用 HMAC,将源 material 作为键,将任何信息(甚至是空消息)作为 HMAC 输入。如果您使用 SHA-384 - 正如已经建议的那样 - 那么输出将是一个整洁的 384 位键控 material 可以用作 SecretKeySpec.

的输入

是的,将 PBKDF2 与 SHA-384、静态或什至空盐和单个迭代(迭代计数为 1)一起使用也可以。但这已经在 .

中提到了

I know this is an uncommon question as no one would be looking for a 384-bit symmetric key size.

嗯,有一个 SIV 操作模式,它欺骗并使用一个真正由两个连续密钥组成的密钥。所以即使是对称密码也有先例。

如果块密码或流密码直接使用 256 位密钥,那么我可能会称它为 snake-oil,因为即使量子计算成为现实,超过 256 位也没有任何意义。


最后,对称密码的密钥只是(伪)随机位 - 包含奇偶校验位的 DES 密钥是奇数位。因此,如果密码与 JCA 不兼容——即你真的不需要 SecretKey 对象实例——你可以只生成一个 48 字节的数组,用 SecureRandom 字节填充它并完成。