如何在两种公钥格式之间转换,一种是“BEGIN RSA PUBLIC KEY”,另一种是“BEGIN PUBLIC KEY”?

162

如何在两种公钥格式之间进行转换,其中一种格式为:

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

另一种格式为:

-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----

例如,我使用ssh-keygen命令生成了id_rsa / id_rsa.pub密钥对, 然后使用以下方法计算id_rsa的公钥:

openssl rsa -in id_rsa -pubout -out pub2 

再次使用以下方法从id_rsa.pub计算公钥:

ssh-keygen -f id_rsa.pub -e -m pem > pub1

内容是pub1:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----

而pub2的内容是:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----
根据我的理解,pub1和pub2包含相同的公钥信息,但是它们的格式不同,我想知道如何在这两种格式之间进行转换?有没有人能给我提供一些简明扼要关于这两种格式的介绍呢? 根据我的理解,pub1和pub2包含相同的公钥信息,但是它们的格式不同,我想知道如何在这两种格式之间进行转换?有没有人能给我提供一些简明扼要关于这两种格式的介绍呢?

Stack Overflow是一个关于编程和开发问题的网站。这个问题似乎不属于编程或开发范畴。请参阅帮助中心中的我可以在这里问什么样的问题。也许超级用户Unix&Linux Stack Exchange更适合提问。 - jww
5个回答

458

我想解释一下这里发生了什么。

一个RSA“公钥”由两个数字组成:

  • 模数(例如,一个2048位的数字)
  • 指数(通常为65537)

以您的RSA公钥为例,这两个数字是:

  • 模数:297056429939040947991047334197581225628107021573849359042679698093131908015712695688944173317630555849768647118986535684992447654339728777985990170679511111819558063246667855023730127805401069042322764200545883378826983730553730138478384327116513143842816383440639376515039682874046227217032079079790098143158087443017552531393264852461292775129262080851633535934010704122673027067442627059982393297716922243940155855127430302323883824137412883916794359982603439112095116831297809626059569444750808699678211904501083183234323797142810155862553705570600021649944369726123996534870137000784980673984909570977377882585701
  • 指数:65537

然后问题就变成了如何在计算机中存储这些数字。首先,我们将它们都转换为十六进制:

  • 模数: 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

此后,其他形式的公钥加密出现了:

  • Diffie-Hellman
  • Ellicptic Curve

当需要创建一个标准来表示那些加密算法的参数时,人们采用了RSA最初定义的许多相同的思想:

  • 使用ASN.1二进制编码
  • 对其进行base64编码
  • 用五个连字符包装它
  • 并加上单词BEGIN PUBLIC KEY

但是,他们决定包括随后的对象标识符(OID)。在RSA公钥的情况下,这是:

  • RSA PKCS#11.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个Base64编码字符

因为在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公钥 格式。


52
哇塞,这真是详尽无遗的信息!谢谢你。这解决了我和一个只期望 "BEGIN RSA PUBLIC KEY" 的 Python 人员之间的问题。然而,在你最后的例子中,好像忘了移除32个字符。 - NullVoxPopuli
10
我用了非常好的 ASN.1 JavaScript 解码器,以及 TRANSLATOR, BINARY 这两个工具都是你工具箱中必备的好帮手。 - Ian Boyd
2
模数的起始位置多了一个字符“1”。它应该像这样开始...... 297,056,429,939,040,947,991,047,334,197,581,225,628,107,02,573... 而不是像这样...... 297,056,429,939,040,947,991,047,334,197,581,225,628,107,021,573... 希望这可以帮助某些人避免因十六进制转换而生气。 - EmpathicSage
2
jsFiddle版本的ASN.1 js。它也在github上。 - Ian Boyd
1
抱歉挑剔一下,但PEM并不是base64的同义词。它有一个复杂而不太明确的历史,但PEM本身就是一种数据格式。通常现在被接受为头部(带有BEGIN XYZ的连字符)、页脚和可选数量的页眉在头部下方,然后是base64编码的数据。 - Luke Joshua Park
显示剩余8条评论

70
我发现这个网站对不同格式的技术解释很好:https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem "BEGIN RSA PUBLIC KEY" 是PKCS#1,只能包含RSA密钥。 "BEGIN PUBLIC KEY" 是SPKI(Subject Public Key Info)密钥(X.509的一部分),可以包含多种格式。 如果你只想用命令行进行转换,"openssl rsa" 是一个很好的选择。 要从SPKI转换为PKCS#1:
openssl rsa -pubin -in <filename> -RSAPublicKey_out

将PKCS#1转换为SPKI:

openssl rsa -RSAPublicKey_in -in <filename> -pubout

5
在 PKCS#8(RFC 5208)中找不到有关公钥的任何内容。 - Franklin Yu
5
@FranklinYu说,是的,PKCS8仅包含私钥,并且PolarSSL在这一点上是错误的。公钥的通用形式由X.509定义,特别是类型SubjectPublicKeyInfo,正如Ian Boyd(长长的!)回答中正确地指出的那样;这些信息在RFC5280中进行了更方便的重复,并根据算法在其他RFC中完成,其中“基本”的RSA在RFC3279中定义。 - dave_thompson_085
4
这个答案是误导性的,正如其他人所指出的 - PKCS#8仅为私钥设置了标准。 - scottysseus
1
@mbed(tls)只是PolarSSL的新名称,正如我之前所说,那是错误的,现在仍然是错误的。看一下PKCS8(RFC5208),那个(publickey)结构在任何地方都不存在;看一下X.509/PKIX(目前为RFC5280),它在第4.1节中。还要看一下RFC7468的第10、11和13节。你可以从PKCS8中_转换_(或提取)公钥,因为(对于现在使用的所有方案)你可以从任何私钥转换公钥,而PKCS8是一个私钥,但没有任何PKCS8不是私钥的地方,就这样,结束了。 - dave_thompson_085
2
PKCS1主要涉及RSA算法,并定义了仅适用于RSA的公钥和私钥。而PKCS8则完全是关于所有算法的私钥,同样地,X.509/PKIX主要涉及所有算法的公钥。 - dave_thompson_085
显示剩余15条评论

14

使用 phpseclib,一个纯PHP的RSA实现...

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
$rsa->loadKey('-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----');
$rsa->setPublicKey();

echo $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW);

尽管标题为BEGIN PUBLIC KEY而不是BEGIN RSA PUBLIC KEY,但base64编码的内容似乎匹配。因此,也许只需使用str_replace来解决这个问题,然后你就可以继续了!


1
我完全不知道为什么该函数读取那个PEM,因为它清楚地描述了X.509中所述的SubjectPublicKeyInfo,而根本没有在PKCS#1中描述,而且二进制内容也与此一致。是的,该结构包含一个PKCS#1编码的RSA私钥,但如果该函数正常工作,则它的允许性就过于宽容了。 - Maarten Bodewes

10

除了页眉/页脚之外,您的pub1和pub2之间唯一的区别是pub2中多了一个字符串:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A。如果您将其删除,则Base 64与pub1中的相同。

根据此答案,额外的字符串对应于算法标识符。


1

将公钥转换为第三种类型的公钥(OpenSSH公钥格式):

输入文件:C:\mc_pubkey.txt:(SSH2公钥格式中的)

---- BEGIN SSH2 PUBLIC KEY ----
Comment: "imported-openssh-key"
AAAAB3NzaC1yc2EAAAADAQABAAABAQCb4oUsXZ51L9DmH3UqSnwOAUr9w6AOZa8b
YH8qsJAhypAjH9YvQteVXXQEY0ybaVE1cmpIKEyC2jmC/jOJ4b7bivlo2hgnLOrj
3FPkDWO2yNNio9RnPXREBx7+iIi9pcaozUmiPMoPxaEyfpGQAvfdFzt+n6+o/hoO
72Zv5RSo0rGr76sLUjx9Mi5TnuI2rT4s9FGMZ9xkgUu3z11UcDhSXqkLEgEEDKBq
bft3VuiQm6Blggzk9tk5L1LAdKM7udhby9dOwXCYPnCKTymYTqi/2FTwKZDj5TJH
V8r6c2Sz/qEdgMkw7RD3ice9m9GYHi2Burgyvjw+Sla+yu0n9sBh
---- END SSH2 PUBLIC KEY ----

要将此内容转换为OpenSSH公钥格式,请使用ssh-keygen.exe实用程序。它可能已经在您的计算机上,因为它是与Git捆绑在一起的。所以在Powershell中:

> cd C:\Program Files\Git\usr\bin

> .\ssh-keygen.exe -i -f "C:\mc_pubkey.txt"
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCb4oUsXZ51L9DmH3UqSnwOAUr9w6AOZa8bYH8qsJAhypAjH9YvQteVXXQEY0ybaVE1cmpIKEyC2jmC/jOJ4b7bivlo2hgnLOrj3FPkDWO2yNNio9RnPXREBx7+iIi9pcaozUmiPMoPxaEyfpGQAvfdFzt+n6+o/hoO72Zv5RSo0rGr76sLUjx9Mi5TnuI2rT4s9FGMZ9xkgUu3z11UcDhSXqkLEgEEDKBqbft3VuiQm6Blggzk9tk5L1LAdKM7udhby9dOwXCYPnCKTymYTqi/2FTwKZDj5TJHV8r6c2Sz/qEdgMkw7RD3ice9m9GYHi2Burgyvjw+Sla+yu0n9sBh

这就是你想要的输出!复制粘贴并保存到文件中,你就完成了。


@MichaelCurrie,你说得很对,但是让我强调一下有很多不同之处 - 细节:头部和尾部的SSH2由4个连字符(而不是5个)和额外的空格分隔 - 注意“data”以AAAA开头而不是MIIB,我相信专家们会解释为什么 - 我的观点是:最重要的是,这些密钥用于不同的用途(主要是SSH/Rsync/SCP/SFTP连接),而不是SSL/TLS...也许我错了 - 你所谓的“conversion”,我会称之为“输出样式/格式”,并且请注意数据以这种“一行”格式存储在.ssh/authorized_keys中。 - Lionel-fr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,