使用 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 用于对称加密和数据验证。
前言:不知道这个问题是在这里问更合适还是在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 用于对称加密和数据验证。