如何存储/检索 RSA 公钥/私钥
我想使用RSA公钥加密。 存储或检索私钥和公钥的最佳方法是什么? XML 在这里是个好主意吗?
如何获得钥匙?
RSAParameters privateKey = RSA.ExportParameters(true);
RSAParameters publicKey = RSA.ExportParameters(false);
因为RSAParameters有以下成员:D、DP、DQ、Exponent、InverseQ、Modulus、P、Q
哪一个是关键?
I want to use RSA public key encryption. What is the best way to store or retrieve private and public keys? Is XML a good idea here?
How to get the keys?
RSAParameters privateKey = RSA.ExportParameters(true);
RSAParameters publicKey = RSA.ExportParameters(false);
Because RSAParameters have the following members: D, DP, DQ, Exponent, InverseQ, Modulus, P, Q
Which one is the key?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我想指出一些事情作为对 ala 的评论的回应,询问是否:
这是完全正确的。 有几种方法可以存储此
指数
+模
。 标准的第一次尝试是在 RFC 3447(公钥密码学标准 (PKCS) #1:RSA 加密规范版本 2.1),它定义了名为RSAPublicKey
:同一个 RFC 继续声明您应该使用 DER 风格的
ASN.1 版本。 1
编码来存储公钥。 我有一个示例公钥:0xDC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 8209 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 995D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55
该公钥的 DER ASN.1 编码为:
如果您采用以上 DER 的全部内容ASN.1 编码
模
+指数
:并且您PEM对其进行编码(即base64):
这是将base64编码数据包装在其中的约定:
这就是您如何获得PEM DER ASN.1 PKCS#1 RSA公钥。
下一个标准是 RFC 4716(安全外壳 (SSH) 公钥文件格式)。 他们在指数和模数之前包含了一个算法标识符 (
ssh-rsa
):他们不想使用 DER ASN.1 编码(因为它极其复杂),而是选择了 4 字节长度前缀:
获取上面的整个字节序列并进行 base-64 编码:
并将其包装在 OpenSSH 标头和尾部中:
注意:OpenSSH 使用四个破折号空格 (
----
),而不是五个破折号且没有空格 (-----
)。下一个标准是 RFC 2459(Internet X.509公钥基础设施证书和 CRL 配置文件)。 他们采用了 PKCS#1 公钥格式:
并将其扩展为包含算法标识符前缀(如果您想使用 RSA 以外的公钥加密算法):
“算法标识符“ RSA 为
1.2.840.113549.1.1 .1
,来自:1
- ISO 分配的 OID1.2
- ISO 成员机构1.2.840
- 美国1.2.840.113549
- RSADSI1.2.840.113549.1
- PKCS1.2.840.113549.1.1
- PKCS-1X.509 是一个糟糕的标准,它定义了一种将
OID
编码为十六进制的极其复杂的方法,但最终X.509SubjectPublicKeyInfo
RSA 公钥的 DER ASN.1 编码是:您可以在解码的 ASN.1 中看到他们如何在旧的
RSAPublicKey
前面加上OBJECT_IDENTIFIER
。采用上述字节并对其进行 PEM(即 base-64)编码:
然后标准是使用类似于 RSA PKCS#1 的标头来包装它,但不带“RSA”(因为它可能是 RSA 以外的东西):
并且这就是您发明X.509SubjectPublicKeyInfo/OpenSSL PEM 公钥格式的方式。
这并不会阻止 RSA 公钥的标准格式列表。 接下来是 OpenSSH 使用的专有公钥格式:
这实际上是上面的 SSH 公钥格式,但前缀为
ssh-rsa
,而不是包裹在---- BEGIN SSH2 PUBLIC KEY ----
/---- END SSH2 PUBLIC KEY ----
中。这就是 XML
RSAKeyValue 公钥
的格式为:
0x 010001
base64 编码为AQAB
这意味着 XML:
更加简单。 缺点是它不能像 Xml 那样很好地进行换行、复制、粘贴(即 Xml 不那么用户友好):
但它是一种很好的中性存储格式。
另请参阅
二进制转换器
I wanted to point out something as a response to a comment by ala asking if:
That is exactly correct. There are a few ways of storing this
exponent
+modulus
. The first attempt at a standard was in RFC 3447 (Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1), which defines a structure for a public key of calledRSAPublicKey
:The same RFC goes on to declare that you should use the DER flavor of
ASN.1
encoding to store the public key. i have a sample public key:0xDC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 8209 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 995D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55
The DER ASN.1 encoding of this public key is:
If you take that entire above DER ASN.1 encoded
modulus
+exponent
:and you PEM encode it (i.e. base64):
It's a convention to wrap that base64 encoded data in:
And that's how you get an have a PEM DER ASN.1 PKCS#1 RSA Public key.
The next standard was RFC 4716 (The Secure Shell (SSH) Public Key File Format). They included an algorithm identifier (
ssh-rsa
), before the exponent and modulus:They didn't want to use DER ASN.1 encoding (as it is horrendously complex), and instead opted for 4-byte length prefixing:
Take the entire above byte sequence and base-64 encode it:
And wrap it in the OpenSSH header and trailer:
Note: That OpenSSH uses four dashes with a space (
----
) rather than five dashes and no space (-----
).The next standard was RFC 2459 (Internet X.509 Public Key Infrastructure Certificate and CRL Profile). They took the PKCS#1 public key format:
and extended it to include an algorithm identifier prefix (in case you want to use a public key encryption algorithm other than RSA):
The "Algorithm Identifier" for RSA is
1.2.840.113549.1.1.1
, which comes from:1
- ISO assigned OIDs1.2
- ISO member body1.2.840
- USA1.2.840.113549
- RSADSI1.2.840.113549.1
- PKCS1.2.840.113549.1.1
- PKCS-1The X.509 is an awful standard, that defines a horribly complicated way of encoding an
OID
into hex, but in the end the DER ASN.1 encoding of an X.509SubjectPublicKeyInfo
RSA Public key is:You can see in the decoded ASN.1 how they just prefixed the old
RSAPublicKey
with anOBJECT_IDENTIFIER
.Taking the above bytes and PEM (i.e. base-64) encoding them:
The standard is then to wrap this with a header similar to RSA PKCS#1, but without the "RSA" (since it could be something other than RSA):
And that's how you invent an X.509 SubjectPublicKeyInfo/OpenSSL PEM public key format.
That doesn't stop the list of standard formats for an RSA public key. Next is the proprietary public key format used by OpenSSH:
Which is actually the SSH public key format above, but prefixed with
ssh-rsa
, rather than wrapped in---- BEGIN SSH2 PUBLIC KEY ----
/---- END SSH2 PUBLIC KEY ----
.This is where the ease of the XML
RSAKeyValue
public key comes in:0x 010001
base64 encoded isAQAB
0x 00 dc 67 fa f4 9e f2 72 1d 45 2c b4 80 79 06 a0 94 27 50 82 09 dd 67 ce 57 b8 6c 4a 4f 40 9f d2 d1 69 fb 99 5d 85 0c 07 a1 f9 47 1b 56 16 6e f6 7f b9 cf 2a 58 36 37 99 29 aa 4f a8 12 e8 4f c7 82 2b 9d 72 2a 9c de 6f c2 ee 12 6d cf f0 f2 b8 c4 dd 7c 5c 1a c8 17 51 a9 ac df 08 22 04 9d 2b d7 f9 4b 09 de 9a eb 5c 51 1a d8 f8 f9 56 9e f8 fb 37 9b 3f d3 74 65 24 0d ff 34 75 57 a4 f5 bf 55
base64 encoded isANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V
.This means the XML is:
Much simpler. A downside is that it doesn't wrap, copy, paste, as nicely as (i.e. Xml is not as user friendly as):
But it makes a great neutral storage format.
See also
Translator, Binary
公钥由模数和指数来标识。 私钥由其他成员识别。
The public key is identified by Modulus and Exponent. The private key is identified by the other members.
我想 @Ian Boyd 的回答并不准确,格式应该是 SSH2,而不是 OpenSSH,因为为 SSH2 定义的 RFC4716,OpenSSH 格式是专有的:
注意:OpenSSH 使用四个带有空格的破折号 (---- )而不是五个破折号且没有空格 (-----)。
I suppose answer from @Ian Boyd would not precisely, the format should be SSH2, instead of OpenSSH, as the RFC4716 defined for SSH2, OpenSSH format have is proprietary:
Note: That OpenSSH uses four dashes with a space (---- ) rather than five dashes and no space (-----).
使用现有的标准格式,例如 PEM。 您的加密库应该提供从 PEM 格式的文件加载和保存密钥的功能。
指数和模数是公钥。 D 和模数是私钥。 其他值允许私钥持有者更快地进行计算。
Use a existing standard format, like PEM. Your crypto library should provide functions to load and save keys from files in PEM format.
Exponent and Modulus are the Public key. D and Modulus are the Private key. The other values allow faster computation for the holder of the Private key.
通常私钥存储在 HSM/智能卡中。 这提供了良好的安全性。
Normally Private keys are stored in HSM's/smart card. This provides a good security.
我成功地将密钥存储为 XML。 RSACryptoServiceProvider 中有两个方法:ToXmlString 和 FromXmlString。 ToXmlString 将返回一个仅包含公钥数据或同时包含公钥和私钥数据的 XML 字符串,具体取决于您设置其参数的方式。 当提供仅包含公钥数据或同时包含公钥和私钥数据的 XML 字符串时,FromXmlString 方法将使用适当的密钥数据填充 RSACryptoServiceProvider。
What I have done successfully is to store the keys as XML. There are two methods in RSACryptoServiceProvider: ToXmlString and FromXmlString. The ToXmlString will return an XML string containing either just the public key data or both the public and private key data depending on how you set its parameter. The FromXmlString method will populate the RSACryptoServiceProvider with the appropriate key data when provided an XML string containing either just the public key data or both the public and private key data.