我想帮助解释这里发生的事情。
RSA “公钥”由两个数字组成:
- 模数(例如2,048位数字)
- 指数(通常为65,537)
以您的RSA公钥为例,这两个数字是:
- 模量:297,056,429,939,040,947,991,047,334,197,581,225,628,107,021,573,849,359,042,679,698,093,131,908, 015,712,695,688,944,173,317,630,555,849,768,647,118,986,535,684,992,447,654,339,728,777,985,990,170, 679,511,111,819,558,063,246,667,855,023,730,127,805,401,069,042,322,764,200,545,883,378,826,983,730, 553,730,138,478,384,327,116,513,143,842,816,383,440,639,376,515,039,682,874,046,227,217,032,079,079,790,098,143,158,087,443,017,552,531,393,264,852,461,292,775,129,262,080,851,633,535,934,010,704,122,673,027,067,442,627,059,982,393,297,716,922,243,940,155,855,127,430,302,323,883,824,137,412,883,916,794,359,982,603,439,112,095,116,831,297,809,626,059,569,444,750,808,699,678,211,904,501,083,183,234,323,797,142,810,155,862,553,705,570,600,021,649,944,369,726,123,996,534,870,137,000,784,980,673,984,909,570,977,377,882,585,701
- 指数:65,537
问题就变成了我们如何将这些数字存储在计算机中。首先,我们将它们都转换为十六进制:
- 模量:EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
- 指数:010001
RSA发明了第一种格式
RSA首先发明了一种格式:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
他们选择使用ASN.1二进制编码标准的DER格式来表示两个数字[1]:
SEQUENCE (2 elements)
INTEGER (2048 bit): EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
INTEGER (24 bit): 010001
ASN.1中的最终二进制编码为:
30 82 01 0A ;sequence (0x10A bytes long)
02 82 01 01 ;integer (0x101 bytes long)
00 EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
02 03 ;integer (3 bytes long)
010001
如果随后将所有这些字节一起运行并进行Base64编码,则会得到:
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
RSA实验室然后说添加标题和尾部:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----
五个连字符和单词BEGIN RSA PUBLIC KEY
。这就是您的PEM DER ASN.1 PKCS#1 RSA公钥
- PEM:base64的同义词
- DER:ASN.1编码的一种形式
- ASN.1:使用的二进制编码方案
- PKCS#1:正式规范,要求将公钥表示为由模数和指数组成的结构
- RSA公钥:正在使用的公钥算法
不只是RSA
之后,出现了其他形式的公共密钥加密:
当需要为表示这些加密算法的参数创建标准时,人们采用了RSA最初定义的许多相同思想:
- 使用ASN.1二进制编码
- base64它
- 用五个连字符包起来
- 和单词
BEGIN PUBLIC KEY
但是不要使用:
-----BEGIN RSA PUBLIC KEY-----
-----BEGIN DH PUBLIC KEY-----
-----BEGIN EC PUBLIC KEY-----
他们决定改为包括随后的对象标识符(OID)。对于RSA公钥,即:
- RSA PKCS#1:
1.2.840.113549.1.1.1
因此,对于RSA公钥,本质上是:
public struct RSAPublicKey {
INTEGER modulus,
INTEGER publicExponent
}
现在他们创建了SubjectPublicKeyInfo,它基本上是:
public struct SubjectPublicKeyInfo {
AlgorithmIdentifier algorithm,
RSAPublicKey subjectPublicKey
}
在实际的DER ASN.1中,定义为:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm ::= SEQUENCE {
algorithm OBJECT IDENTIFIER, -- 1.2.840.113549.1.1.1 rsaEncryption (PKCS#1 1)
parameters ANY DEFINED BY algorithm OPTIONAL },
subjectPublicKey BIT STRING {
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
}
这将为您提供ASN.1:
SEQUENCE (2 elements)
SEQUENCE (2 elements)
OBJECT IDENTIFIER 1.2.840.113549.1.1.1
NULL
BIT STRING (1 element)
SEQUENCE (2 elements)
INTEGER (2048 bit): EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
INTEGER (24 bit): 010001
ASN.1中的最终二进制编码为:
30 82 01 22 ;SEQUENCE (0x122 bytes = 290 bytes)
| 30 0D ;SEQUENCE (0x0d bytes = 13 bytes)
| | 06 09 ;OBJECT IDENTIFIER (0x09 = 9 bytes)
| | 2A 86 48 86
| | F7 0D 01 01 01 ;hex encoding of 1.2.840.113549.1.1
| | 05 00 ;NULL (0 bytes)
| 03 82 01 0F 00 ;BIT STRING (0x10f = 271 bytes)
| | 30 82 01 0A ;SEQUENCE (0x10a = 266 bytes)
| | | 02 82 01 01 ;INTEGER (0x101 = 257 bytes)
| | | | 00 ;leading zero of INTEGER
| | | | EB 50 63 99 F5 C6 12 F5 A6 7A 09 C1 19 2B 92 FA
| | | | B5 3D B2 85 20 D8 59 CE 0E F6 B7 D8 3D 40 AA 1C
| | | | 1D CE 2C 07 20 D1 5A 0F 53 15 95 CA D8 1B A5 D1
| | | | 29 F9 1C C6 76 97 19 F1 43 58 72 C4 BC D0 52 11
| | | | 50 A0 26 3B 47 00 66 48 9B 91 8B FC A0 3C E8 A0
| | | | E9 FC 2C 03 14 C4 B0 96 EA 30 71 7C 03 C2 8C A2
| | | | 9E 67 8E 63 D7 8A CA 1E 9A 63 BD B1 26 1E E7 A0
| | | | B0 41 AB 53 74 6D 68 B5 7B 68 BE F3 7B 71 38 28
| | | | 38 C9 5D A8 55 78 41 A3 CA 58 10 9F 0B 4F 77 A5
| | | | E9 29 B1 A2 5D C2 D6 81 4C 55 DC 0F 81 CD 2F 4E
| | | | 5D B9 5E E7 0C 70 6F C0 2C 4F CA 35 8E A9 A8 2D
| | | | 80 43 A4 76 11 19 55 80 F8 94 58 E3 DA B5 59 2D
| | | | EF E0 6C DE 1E 51 6A 6C 61 ED 78 C1 39 77 AE 96
| | | | 60 A9 19 2C A7 5C D7 29 67 FD 3A FA FA 1F 1A 2F
| | | | F6 32 5A 50 64 D8 47 02 8F 1E 6B 23 29 E8 57 2F
| | | | 36 E7 08 A5 49 DD A3 55 FC 74 A3 2F DD 8D BA 65
| | | 02 03 ;INTEGER (03 = 3 bytes)
| | | | 010001
和以前一样,您将所有这些字节都用Base64编码,最后得到第二个示例:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
添加稍有不同的标题和结尾,您将获得:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----
这是您的X.509 SubjectPublicKeyInfo / OpenSSL PEM公钥 [2]。
正确执行或修改
既然您知道编码并不是魔术,那么您就可以编写解析RSA模数和指数所需的所有片段。或者您可以认识到前24个字节只是在原始PKCS#1标准之上添加了新内容
30 82 01 22 ;SEQUENCE (0x122 bytes = 290 bytes)
| 30 0D ;SEQUENCE (0x0d bytes = 13 bytes)
| | 06 09 ;OBJECT IDENTIFIER (0x09 = 9 bytes)
| | 2A 86 48 86
| | F7 0D 01 01 01 ;hex encoding of 1.2.840.113549.1.1
| | 05 00 ;NULL (0 bytes)
| 03 82 01 0F 00 ;BIT STRING (0x10f = 271 bytes)
| | ...
这些前24个字节是添加的“新”内容:
30 82 01 22 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 82 01 0F 00
由于运气和好运的巧合:
24个字节正好对应恰好 32个64位编码的字符
因为在Base64中:3个字节变为四个字符:
30 82 01 22 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 82 01 0F 00
\______/ \______/ \______/ \______/ \______/ \______/ \______/ \______/
| | | | | | | |
MIIB IjAN Bgkq hkiG 9w0B AQEF AAOC AQ8A
这意味着,如果您使用第二个X.509公钥,则前32个字符仅对应于新添加的内容:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END PUBLIC KEY-----
如果您删除前32个字符,并将其更改为BEGIN RSA PUBLIC KEY:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----
您正是想要的-旧的RSA PUBLIC KEY
格式。