如何从 DH 密钥获取 AES 密钥
How to get AES secret key from DH secret key
我有以下代码将 DH 密钥转换为 AES 密钥。这曾经一直有效,直到 Oracle JRE 8u161 他们开始限制在 java.security
文件中创建小于 1024 的 DH 密钥。现在,我将在最后一行得到 NoSuchAlgorithmException: Unsupported secret key algorithm AES
。
PrivateKey privKey = null;
PublicKey pubKey = null;
PublicKey agreement = null;
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privKey);
keyAgreement.doPhase(pubKey, false);
keyAgreement.doPhase(agreement, true);
SecretKey key = keyAgreement.generateSecret("AES");
我试着把最后一行改成这个。我可以使用新密钥进行加密和解密,但这不适用于之前生成的旧密钥。
byte[] encodedKey = keyAgreement.generateSecret();
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
我发现了一个类似的 SO 问题 What metod KeyAgreement.generateSecret(String algorithm) does? 但我仍然不知道如何在不破坏现有密钥的情况下解决这个问题。
通常,密钥大小要求在 Cipher
和 KeyAgreement
class 本身中检查,而不是在提供商的服务实施中检查。当然,无论 [EDIT 是什么,都会尝试测试另一个提供程序,例如 Bouncy Castle 提供程序:这似乎在这种情况下有效,因此密钥大小限制在随附的默认提供程序中Java 运行时,使用 "BC" 提供程序似乎工作正常,]。
如果使用其他提供商不起作用,则使用 Bouncy Castle 轻量级 API(org.bouncycastle.**
classes)使用另一个 DH 软件实现,绕过 KeyAgreement
class 一共。然而,应避免走出 JCA / KeyAgreement
。
不用说,不使用 < 1024 位密钥的要求是有原因的,它们不再被认为是安全的。尽快升级您的安全系统!
Oracle/Sun-providers 的问题不是 java.security 中的 DH keysize 限制,它仅适用于 TLS/SSL(即 JSSE),但该项目在发行说明中稍微靠下您已链接:
- Stricter key generation
The generateSecret(String)
method has been mostly disabled in the javax.crypto.KeyAgreement
services of the SunJCE and SunPKCS11 providers. Invoking this method for these providers will result in a NoSuchAlgorithmException
for most algorithm string arguments. The previous behavior of this method can be re-enabled by setting the value of the jdk.crypto.KeyAgreement.legacyKDF
system property to true
(case insensitive). Re-enabling this method by setting this system property is not recommended.
后面几段基本上说了,不是很清楚,正确使用DH需要合适的KDF,但是这个操作没有provide/defineKDF,所以不能保证合适,应该使用无参数 generateSecretKey()
方法获取原始 DH 值并自己应用合适的 KDF;他们以 SP800-56Ar2 和纯哈希为例。
BouncyCastle 反其道而行之;在 1.60 中,它有几个 KeyAgreement
算法,其中 KDF 编码为 DHwithSHA256CKDF
.
我有以下代码将 DH 密钥转换为 AES 密钥。这曾经一直有效,直到 Oracle JRE 8u161 他们开始限制在 java.security
文件中创建小于 1024 的 DH 密钥。现在,我将在最后一行得到 NoSuchAlgorithmException: Unsupported secret key algorithm AES
。
PrivateKey privKey = null;
PublicKey pubKey = null;
PublicKey agreement = null;
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privKey);
keyAgreement.doPhase(pubKey, false);
keyAgreement.doPhase(agreement, true);
SecretKey key = keyAgreement.generateSecret("AES");
我试着把最后一行改成这个。我可以使用新密钥进行加密和解密,但这不适用于之前生成的旧密钥。
byte[] encodedKey = keyAgreement.generateSecret();
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
我发现了一个类似的 SO 问题 What metod KeyAgreement.generateSecret(String algorithm) does? 但我仍然不知道如何在不破坏现有密钥的情况下解决这个问题。
通常,密钥大小要求在 Cipher
和 KeyAgreement
class 本身中检查,而不是在提供商的服务实施中检查。当然,无论 [EDIT 是什么,都会尝试测试另一个提供程序,例如 Bouncy Castle 提供程序:这似乎在这种情况下有效,因此密钥大小限制在随附的默认提供程序中Java 运行时,使用 "BC" 提供程序似乎工作正常,
如果使用其他提供商不起作用,则使用 Bouncy Castle 轻量级 API(org.bouncycastle.**
classes)使用另一个 DH 软件实现,绕过 KeyAgreement
class 一共。然而,应避免走出 JCA / KeyAgreement
。
不用说,不使用 < 1024 位密钥的要求是有原因的,它们不再被认为是安全的。尽快升级您的安全系统!
Oracle/Sun-providers 的问题不是 java.security 中的 DH keysize 限制,它仅适用于 TLS/SSL(即 JSSE),但该项目在发行说明中稍微靠下您已链接:
- Stricter key generation
The
generateSecret(String)
method has been mostly disabled in thejavax.crypto.KeyAgreement
services of the SunJCE and SunPKCS11 providers. Invoking this method for these providers will result in aNoSuchAlgorithmException
for most algorithm string arguments. The previous behavior of this method can be re-enabled by setting the value of thejdk.crypto.KeyAgreement.legacyKDF
system property totrue
(case insensitive). Re-enabling this method by setting this system property is not recommended.
后面几段基本上说了,不是很清楚,正确使用DH需要合适的KDF,但是这个操作没有provide/defineKDF,所以不能保证合适,应该使用无参数 generateSecretKey()
方法获取原始 DH 值并自己应用合适的 KDF;他们以 SP800-56Ar2 和纯哈希为例。
BouncyCastle 反其道而行之;在 1.60 中,它有几个 KeyAgreement
算法,其中 KDF 编码为 DHwithSHA256CKDF
.