使用 ECDH public 密钥进行密钥包装?

Key wrapping with an ECDH public key?

前言:不知道这个问题是在这里问更合适还是在Crypto网站上问更合适。随意移动或删除或任何适当的 SE 操作。


我被要求帮助更新一些加密软件。从广义上讲,该软件已经完成了以下步骤,其中 none 个特别不寻常。为了简化 posting:

,我省略了错误处理和 Provider 参数

1) 生成用于 AES-128(或 AES-256,mutatis mutandis)的随机对称密钥:

KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init (128, a_SecureRandom_instance);
SecretKey sessionKey = keygen.generateKey();

2) 包装对称密钥,具体取决于用户是否使用...
2a) ...来自密钥对的 RSA public 密钥:

// OAEP wasn't used in this software for hysterical raisins
Cipher wrapper = Cipher.getInstance("RSA/ECB/PKCS1Padding");
wrapper.init (Cipher.WRAP_MODE, user_RSA_PublicKey);

2b) ...密码:

SecretKey stretched = ...passphrase stretched through a PBKDF like bcrypt...;
// I don't remember whether it's specified as "AES" or "AESWrap" here
Cipher wrapper = Cipher.getInstance("AES or AESWrap/ECB/NoPadding");
wrapper.init (Cipher.WRAP_MODE, stretched);

2c) 任一路由,会话密钥被包装:

byte[] wrapped = wrapper.wrap(sessionKey);

3) 会话密钥用于使用 Cipher.ENCRYPT_MODE 和随机 IV 创建 Cipher,然后通过它卸载数据 运行。该部分非常标准,但如果您真的想查看 CipherInputStream 用法,我可以 post 它。包装的会话密钥与加密数据和一堆 HMAC 一起存储在阳光下。

稍后在解密时,用户提供 RSA 私钥或用于拉伸的密码;软件解开对称密钥并解密数据。

所有这些都已经工作了一段时间。但是当然 RSA 密钥对变得越来越大和越来越慢,所以他们希望支持上面步骤 #2 的额外可能性,其中 public 密钥是使用椭圆曲线算法生成的(P384 ECDH 是通常的情况).这就是我们感到困惑的地方。

Cipher wrapper = Cipher.getInstance("RSA/ECB/PKCS1Padding") 调用中似乎没有 JCE 替代 algorithm/transformation 椭圆曲线。 Java 文档中唯一列出的是 "ECIES",它似乎(?)更倾向于多方密钥协议?

我可以为 Java 内置 JCE 找到的所有 API,甚至查看 Bouncy Castle,都只在密钥协议和传输的上下文中提及 ECDH 密钥,它们用于 生成一个对称密钥而不是包装一个现有密钥。

我觉得我们在这里遗漏了一些东西,可能是因为假设不当。 Cipher.wrap() 真的不是 ECDH 密钥的选项吗?或者它 ,但我们需要做一些时髦的事情才能创建 ECIES Cipher 实例?

RSA 是一种用于加密和签名的算法(或者取决于您如何看待它,两种非常相似但截然不同的算法)。 RSA加密可以加密数据,它是一个(低级)密钥,在这种情况下它被称为包装。

DH 是一种密钥协商算法,无论是经典形式(又名整数、Zp、modp 或 finite-field/FF)还是椭圆形式-曲线形式(ECDH)。请注意,至少对于经典 DH,原始协议值 g^a^b mod n = g^b^a mod n 具有足够的数学结构,人们不愿意直接将其用作密钥,所以我们 运行 它通过一个密钥推导函数,缩写为 KDF。我不清楚 ECDH 值是否真的需要 KDF,至少对于包括 P384 在内的常用 X9/NIST 曲线(如果你关心,你可能会查看或询问 crypto.SX),但是使用 KDF 很便宜而且行之有效,所以我们这样做。

我从来没有听说过有人称呼 (EC)DH 密钥传输,因为它不是。它 包含在关键字 exchange 中,该术语旨在涵盖传输和协议的(有用的)结合。

您可以创建一个 加密方案 使用 (EC)DH 通过使用约定的(和派生的)值作为对称的密钥加密——而且 (EC)IES. 我不知道是什么让您认为 IES 是别的东西。现代实践是对称加密应该被认证,并且 IES 的标准化形式作为一个单独的方案使用 CBC 加密和 HMAC 认证,尽管你可以有效地设计一个方案,例如使用改为使用 GCM。

如您所见,BouncyCastle 提供程序提供 DH(经典)或 EC IES“with{AES,DESEDE}-CBC”(在 1.56 之前的版本中,-CBC 有时被省略)的实现,它们使用 P1363a 中的 KDF2 和SHA1、指示的 CBC 密码和 HMAC-SHA1。 'standard' (Sun/Oracle/Open) 提供者不这样做,但您可以结合原始协议操作、KDF、对称加密和 MAC 来产生相同的结果。

这与CMS-formerly-PKCS7 with classic DH and ECDH and PGP with ECDH的操作类似(虽然在某些细节上有所不同)。 (PGP 不支持经典 DH;它使用 ElGamal 加密代替 RSA。)更不用说使用经典或 EC DH 'exchange' 的 TLS(有时通过 1.2,总是在 1.3)和 SSH ,并且通常是短暂的,而不是至少有静态的接收者)来产生一个秘密,该秘密被派生并用作密钥 material 用于对称加密和数据验证。