Java 如何从DH密钥中获取AES密钥

Java 如何从DH密钥中获取AES密钥,java,encryption,cryptography,aes,diffie-hellman,Java,Encryption,Cryptography,Aes,Diffie Hellman,我有以下代码将DH密钥转换为AES密钥。这一直有效,直到他们开始限制在java.security文件中创建

我有以下代码将DH密钥转换为AES密钥。这一直有效,直到他们开始限制在
java.security
文件中创建<1024个DH密钥。现在,我将在最后一行获得
nosuchalgorithexception:Unsupported secret key algorithmaes

PrivateKey privKey=null;
PublicKey pubKey=null;
公钥协议=空;
KeyAgreement KeyAgreement=KeyAgreement.getInstance(“DH”);
keyAgreement.init(privKey);
keyAgreement.doPhase(pubKey,false);
keyAgreement.doPhase(协议,真实);
SecretKey=keyagression.generateSecret(“AES”);
我试着把最后一行改成这个。我可以使用新密钥加密和解密,但这不适用于以前生成的旧密钥

byte[]encodedKey=keyAgreement.GenerateCret();
SecretKey key=newsecretkeyspec(encodedKey,0,encodedKey.length,“AES”);

我发现了一个类似的SO问题,但我仍然不知道如何在不破坏现有密钥的情况下修复此问题。

通常,密钥大小要求是在
密码
密钥协议
类本身中检查的,而不是由提供商执行的服务。当然,我们可以尝试测试另一个提供程序,例如Bouncy Castle提供程序,不管它是什么[EDIT:在这种情况下,这似乎是可行的,因此关键大小限制在Java运行时提供的默认提供程序中,使用“BC”提供程序似乎可以正常工作,]

如果使用其他提供程序无效,则使用Bouncy Castle轻量级API(
org.bouncycastle.*
classes)来使用DH的另一个软件实现,完全绕过
KeyAgreement
类。但是,应避免跳出JCA/
关键协议


不用说,不使用<1024位密钥的要求是有原因的,它们不再被认为是安全的。尽快升级您的安全

Oracle/Sun providers的问题不在于java.security中的DH keysize限制,该限制仅适用于TLS/SSL(即JSSE),而是您链接的发行说明中稍微向下一点的这一项:

  • 更严格的密钥生成
SunJCE和SunPKCS11提供商的
javax.crypto.KeyAgreement
服务中,generateScret(String)
方法大部分已被禁用。为这些提供程序调用此方法将导致大多数算法字符串参数出现
NoSuchAlgorithmException
。通过将
jdk.crypto.keyargreement.legacyKDF
系统属性的值设置为
true
(不区分大小写),可以重新启用此方法以前的行为。不建议通过设置此系统属性重新启用此方法

接下来的段落基本上说(不是很清楚),正确使用DH需要合适的KDF,但此操作不提供/定义KDF,因此无法确保适合性,相反,您应该使用无参数
generateScretKey()
方法来获取原始DH值并自己应用合适的KDF;他们给出了SP800-56Ar2和普通散列作为示例


BouncyCastle走了另一条路;在1.60中,它有几个KDF编码的
KeyAgreement
算法,如
DHwithSHA256CKDF

谢谢你的回答。我们已经添加了BC作为提供者,但我们没有明确使用它。将
KeyAgreement
初始化为
KeyAgreement.getInstance(“DH”、“BC”)
确实解决了我们目前的问题。