如何存储/检索 RSA 公钥/私钥

发布于 2024-07-30 06:44:38 字数 297 浏览 4 评论 0原文

我想使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不交电费瞎发啥光 2024-08-06 06:44:38

我想指出一些事情作为对 ala 的评论的回应,询问是否:

公钥=模数+指数

这是完全正确的。 有几种方法可以存储此指数 + 。 标准的第一次尝试是在 RFC 3447公钥密码学标准 (PKCS) #1:RSA 加密规范版本 2.1),它定义了名为 RSAPublicKey

RSAPublicKey ::= SEQUENCE {
      modulus           INTEGER,  -- n
      publicExponent    INTEGER   -- e
  }

同一个 RFC 继续声明您应该使用 DER 风格的 ASN.1 版本。 1编码来存储公钥。 我有一个示例公钥:

  • publicExponent:65537(按照惯例,所有 RSA 公钥都使用 65537 作为指数)
  • 模数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 编码为:

30 81 89          ;SEQUENCE (0x89 bytes = 137 bytes)
|  02 81 81       ;INTEGER (0x81 bytes = 129 bytes)
|  |  00          ;leading zero of INTEGER
|  |  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
|  02 03          ;INTEGER (0x03 = 3 bytes)
|  |  01 00 01    ;hex for 65537. see it?

如果您采用以上 DER 的全部内容ASN.1 编码+指数

30 81 89 02 81 81 00 直流 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 交流 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 02 03 01
00 01

并且您PEM对其进行编码(即base64):

MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY
UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE
3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV
ek9b9VAgMBAAE=

这是将base64编码数据包装在其中的约定:

-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY
UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE
3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV
ek9b9VAgMBAAE=
-----END RSA PUBLIC KEY-----

这就是您如何获得PEM DER ASN.1 PKCS#1 RSA公钥。


下一个标准是 RFC 4716安全外壳 (SSH) 公钥文件格式)。 他们在指数和模数之前包含了一个算法标识符 (ssh-rsa):

string    "ssh-rsa"
mpint     e
mpint     n

他们不想使用 DER ASN.1 编码(因为它极其复杂),而是选择了 4 字节长度前缀

00000007                 ;7 byte algorithm identifier
73 73 68 2d 72 73 61     ;"ssh-rsa"
00000003                 ;3 byte exponent
01 00 01                 ;hex for 65,537 
00000080                 ;128 byte modulus
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

获取上面的整个字节序列并进行 base-64 编码:

AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs
Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4S
bc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80
dVek9b9V

并将其包装在 OpenSSH 标头和尾部中:

---- BEGIN SSH2 PUBLIC KEY ----
AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs
Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4S
bc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80
dVek9b9V
---- END SSH2 PUBLIC KEY ----

注意:OpenSSH 使用四个破折号空格 (----),而不是五个破折号且没有空格 (-----)。


下一个标准是 RFC 2459Internet X.509公钥基础设施证书和 CRL 配置文件)。 他们采用了 PKCS#1 公钥格式:

RSAPublicKey ::= SEQUENCE {
      modulus           INTEGER,  -- n
      publicExponent    INTEGER   -- e
  }

并将其扩展为包含算法标识符前缀(如果您想使用 RSA 以外的公钥加密算法):

SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm            AlgorithmIdentifier,
    subjectPublicKey     RSAPublicKey }

“算法标识符“ RSA 为 1.2.840.113549.1.1 .1,来自:

  • 1 - ISO 分配的 OID
    • 1.2 - ISO 成员机构
      • 1.2.840 - 美国
        • 1.2.840.113549 - RSADSI
          • 1.2.840.113549.1 - PKCS
            • 1.2.840.113549.1.1 - PKCS-1

X.509 是一个糟糕的标准,它定义了一种将 OID 编码为十六进制的极其复杂的方法,但最终X.509 SubjectPublicKeyInfo RSA 公钥的 DER ASN.1 编码是:

30 81 9F            ;SEQUENCE (0x9f bytes = 159 bytes)
|  30 0D            ;SEQUENCE (0x0d bytes = 13 bytes)
|  |  06 09         ;OBJECT_IDENTIFIER (0x09 = 9 bytes)
|  |  2A 86 48 86   ;Hex encoding of 1.2.840.113549.1.1
|  |  F7 0D 01 01 01
|  |  05 00         ;NULL (0 bytes)
|  03 81 8D 00      ;BIT STRING (0x8d bytes = 141 bytes)
|  |  30 81 89          ;SEQUENCE (0x89 bytes = 137 bytes)
|  |  |  02 81 81       ;INTEGER (0x81 bytes = 129 bytes)
|  |  |  00          ;leading zero of INTEGER
|  |  |  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
|  |  02 03          ;INTEGER (0x03 = 3 bytes)
|  |  |  01 00 01    ;hex for 65537. see it?

您可以在解码的 ASN.1 中看到他们如何在旧的 RSAPublicKey 前面加上 OBJECT_IDENTIFIER

采用上述字节并对其进行 PEM(即 base-64)编码:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcZ/r0nvJyHUUstIB5BqCUJ1CC
Cd1nzle4bEpPQJ/S0Wn7mV2FDAeh+UcbVhZu9n+5zypYNjeZKapPqBLoT8eCK51y
Kpzeb8LuEm3P8PK4xN18XBrIF1GprN8IIgSdK9f5SwnemutcURrY+PlWnvj7N5s/
03RlJA3/NHVXpPW/VQIDAQAB

然后标准是使用类似于 RSA PKCS#1 的标头来包装它,但不带“RSA”(因为它可能是 RSA 以外的东西):

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcZ/r0nvJyHUUstIB5BqCUJ1CC
Cd1nzle4bEpPQJ/S0Wn7mV2FDAeh+UcbVhZu9n+5zypYNjeZKapPqBLoT8eCK51y
Kpzeb8LuEm3P8PK4xN18XBrIF1GprN8IIgSdK9f5SwnemutcURrY+PlWnvj7N5s/
03RlJA3/NHVXpPW/VQIDAQAB
-----END PUBLIC KEY-----

并且这就是您发明X.509SubjectPublicKeyInfo/OpenSSL PEM 公钥格式的方式。


这并不会阻止 RSA 公钥的标准格式列表。 接下来是 OpenSSH 使用的专有公钥格式:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsg XUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V

这实际上是上面的 SSH 公钥格式,但前缀为 ssh-rsa,而不是包裹在 ---- BEGIN SSH2 PUBLIC KEY ----/---- END SSH2 PUBLIC KEY ---- 中。


这就是 XML RSAKeyValue 公钥的格式为:

  • 指数0x 010001 base64 编码为AQAB
  • 模数:<代码>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 1乙 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 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 编码为 ANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7h sSK9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/ lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V。

这意味着 XML:

<RSAKeyValue>
   <Modulus>ANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V</Modulus>
   <Exponent>AQAB</Exponent>
</RSAKeyValue>

更加简单。 缺点是它不能像 Xml 那样很好地进行换行、复制、粘贴(即 Xml 不那么用户友好):

-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY
UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE
3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV
ek9b9VAgMBAAE=
-----END RSA PUBLIC KEY-----

但它是一种很好的中性存储格式。

另请参阅

  • 二进制转换器:非常适合解码和编码 base64 data
  • ASN.1 JavaScript 解码器:非常适合解码 ASN.1 编码的十六进制数据(您从二进制转换器
  • Microsoft ASN.1 文档:描述用于 ASN.1 结构的杰出编码规则 (DER)(您找不到更好的一组其他地方的文档;我认为微软的文档不仅仅是真正的文档)

I wanted to point out something as a response to a comment by ala asking if:

Public Key = modulus + exponent

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 called RSAPublicKey:

RSAPublicKey ::= SEQUENCE {
      modulus           INTEGER,  -- n
      publicExponent    INTEGER   -- e
  }

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:

  • publicExponent: 65537 (it is convention that all RSA public keys use 65537 as their exponent)
  • modulus: 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:

30 81 89          ;SEQUENCE (0x89 bytes = 137 bytes)
|  02 81 81       ;INTEGER (0x81 bytes = 129 bytes)
|  |  00          ;leading zero of INTEGER
|  |  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
|  02 03          ;INTEGER (0x03 = 3 bytes)
|  |  01 00 01    ;hex for 65537. see it?

If you take that entire above DER ASN.1 encoded modulus+exponent:

30 81 89 02 81 81 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 02 03 01
00 01

and you PEM encode it (i.e. base64):

MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY
UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE
3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV
ek9b9VAgMBAAE=

It's a convention to wrap that base64 encoded data in:

-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY
UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE
3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV
ek9b9VAgMBAAE=
-----END RSA PUBLIC KEY-----

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:

string    "ssh-rsa"
mpint     e
mpint     n

They didn't want to use DER ASN.1 encoding (as it is horrendously complex), and instead opted for 4-byte length prefixing:

00000007                 ;7 byte algorithm identifier
73 73 68 2d 72 73 61     ;"ssh-rsa"
00000003                 ;3 byte exponent
01 00 01                 ;hex for 65,537 
00000080                 ;128 byte modulus
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

Take the entire above byte sequence and base-64 encode it:

AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs
Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4S
bc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80
dVek9b9V

And wrap it in the OpenSSH header and trailer:

---- BEGIN SSH2 PUBLIC KEY ----
AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs
Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4S
bc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80
dVek9b9V
---- END SSH2 PUBLIC KEY ----

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:

RSAPublicKey ::= SEQUENCE {
      modulus           INTEGER,  -- n
      publicExponent    INTEGER   -- e
  }

and extended it to include an algorithm identifier prefix (in case you want to use a public key encryption algorithm other than RSA):

SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm            AlgorithmIdentifier,
    subjectPublicKey     RSAPublicKey }

The "Algorithm Identifier" for RSA is 1.2.840.113549.1.1.1, which comes from:

  • 1 - ISO assigned OIDs
    • 1.2 - ISO member body
      • 1.2.840 - USA
        • 1.2.840.113549 - RSADSI
          • 1.2.840.113549.1 - PKCS
            • 1.2.840.113549.1.1 - PKCS-1

The 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.509 SubjectPublicKeyInfo RSA Public key is:

30 81 9F            ;SEQUENCE (0x9f bytes = 159 bytes)
|  30 0D            ;SEQUENCE (0x0d bytes = 13 bytes)
|  |  06 09         ;OBJECT_IDENTIFIER (0x09 = 9 bytes)
|  |  2A 86 48 86   ;Hex encoding of 1.2.840.113549.1.1
|  |  F7 0D 01 01 01
|  |  05 00         ;NULL (0 bytes)
|  03 81 8D 00      ;BIT STRING (0x8d bytes = 141 bytes)
|  |  30 81 89          ;SEQUENCE (0x89 bytes = 137 bytes)
|  |  |  02 81 81       ;INTEGER (0x81 bytes = 129 bytes)
|  |  |  00          ;leading zero of INTEGER
|  |  |  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
|  |  02 03          ;INTEGER (0x03 = 3 bytes)
|  |  |  01 00 01    ;hex for 65537. see it?

You can see in the decoded ASN.1 how they just prefixed the old RSAPublicKey with an OBJECT_IDENTIFIER.

Taking the above bytes and PEM (i.e. base-64) encoding them:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcZ/r0nvJyHUUstIB5BqCUJ1CC
Cd1nzle4bEpPQJ/S0Wn7mV2FDAeh+UcbVhZu9n+5zypYNjeZKapPqBLoT8eCK51y
Kpzeb8LuEm3P8PK4xN18XBrIF1GprN8IIgSdK9f5SwnemutcURrY+PlWnvj7N5s/
03RlJA3/NHVXpPW/VQIDAQAB

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):

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcZ/r0nvJyHUUstIB5BqCUJ1CC
Cd1nzle4bEpPQJ/S0Wn7mV2FDAeh+UcbVhZu9n+5zypYNjeZKapPqBLoT8eCK51y
Kpzeb8LuEm3P8PK4xN18XBrIF1GprN8IIgSdK9f5SwnemutcURrY+PlWnvj7N5s/
03RlJA3/NHVXpPW/VQIDAQAB
-----END PUBLIC KEY-----

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:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V

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:

  • Exponent: 0x 010001 base64 encoded is AQAB
  • Modulus: 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 is ANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V.

This means the XML is:

<RSAKeyValue>
   <Modulus>ANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V</Modulus>
   <Exponent>AQAB</Exponent>
</RSAKeyValue>

Much simpler. A downside is that it doesn't wrap, copy, paste, as nicely as (i.e. Xml is not as user friendly as):

-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY
UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE
3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV
ek9b9VAgMBAAE=
-----END RSA PUBLIC KEY-----

But it makes a great neutral storage format.

See also

  • Translator, Binary: Great for decoding and encoding base64 data
  • ASN.1 JavaScript decoder: Great for decoding ASN.1 encoded hex data (that you get from Translator, Binary
  • Microsoft ASN.1 Documentation: Describes the Distinguished Encoding Rules (DER) used for ASN.1 structures (you won't find a better set of documentation anywhere else; i would argue Microsoft's is not only real documentation)
赠意 2024-08-06 06:44:38

公钥由模数和指数来标识。 私钥由其他成员识别。

The public key is identified by Modulus and Exponent. The private key is identified by the other members.

你在看孤独的风景 2024-08-06 06:44:38

我想 @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 (-----).

南笙 2024-08-06 06:44:38

使用现有的标准格式,例如 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.

关于从前 2024-08-06 06:44:38

XML 在这里是个好主意吗?

通常私钥存储在 HSM/智能卡中。 这提供了良好的安全性。

Is XML a good idea here?

Normally Private keys are stored in HSM's/smart card. This provides a good security.

秋风の叶未落 2024-08-06 06:44:38

我成功地将密钥存储为 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文