从X509Certificate2生成的十六进制字符串还原RSA公钥失败
数字签名项目公钥转换与解密问题
开发数字签名项目时,获取到通过X509Certificate2.GetPublicKeyString()生成的十六进制公钥字符串:
3082010A0282010100D8F165280738A827AA1D2960D09ECA7EA3928BC3B6BA4CF034BEFE6E00DB434793B96C2FD2411BE086B6CE4B30441D18DFF377497F99F043E74B2C30555D2157C2838C9E7BDD566F0633CC0BE6F2649278BB8FE15EB2D4020C087B2252D8ED024DD260A3AA07F399D90EBDA722BEFECAD6D7A011A30F9013C4AFE3E15BA5E5B9028DE51079CDE125555B82E4269699E662D8BF182DF173FCC90135FC117B8254BF7036FE0A9B0667C0266E8EF94F9EE630CA0CF611FF0BB2BBFD99A7B9D9CC6C93D272A7DC87FE59D35C34D9487F1038179C6576114994C942F826168BDF112DD17FC5725684AE74359FED8C753D1D7F01AB8F5A070E93DD89CA0C9BC2520C850203010001
尝试通过以下代码将其转换为PEM格式:
byte[] certBytes = Enumerable.Range(0, certHex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(certHex.Substring(x, 2), 16)) .ToArray(); string certPem = "-----BEGIN RSA PUBLIC KEY-----\n" + Convert.ToBase64String(certBytes, Base64FormattingOptions.InsertLineBreaks) .TrimEnd() + "\n-----END RSA PUBLIC KEY-----\n";
生成的PEM如下(实际生成时错误使用了CERTIFICATE标签):
-----BEGIN CERTIFICATE----- MIIBCgKCAQEA2PFlKAc4qCeqHSlg0J7KfqOSi8O2ukzwNL7+bgDbQ0eTuWwv0kEb4Ia2zkswRB0Y 3/N3SX+Z8EPnSywwVV0hV8KDjJ573VZvBjPMC+byZJJ4u4/hXrLUAgwIeyJS2O0CTdJgo6oH85nZ Dr2nIr7+ytbXoBGjD5ATxK/j4Vul5bkCjeUQec3hJVVbguQmlpnmYti/GC3xc/zJATX8EXuCVL9w Nv4KmwZnwCZujvlPnuYwygz2Ef8Lsrv9mae52cxsk9Jyp9yH/lnTXDTZSH8QOBecZXYRSZTJQvgm FovfES3Rf8VyVoSudDWf7Yx1PR1/AauPWgcOk92JygybwlIMhQIDAQAB -----END CERTIFICATE-----
遇到的问题:
- 执行
X509Certificate2 cert = new X509Certificate2(Encoding.ASCII.GetBytes(certPem));时加载失败 - 使用以下解密逻辑时,调用
Decrypt抛出异常:Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'Key does not exist.'
csp = RSA.Create(); csp.ImportFromPem(certPem.ToCharArray()); var decryptedBytes = csp.Decrypt(encryptedData, RSAEncryptionPadding.Pkcs1);
解决思路
- 修正PEM标签:
X509Certificate2.GetPublicKeyString()返回的是SubjectPublicKeyInfo格式的ASN.1 DER编码,对应的PEM标签应为-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----,而非RSA PUBLIC KEY或CERTIFICATE(后者用于完整证书,不是单独公钥)。 - 修正转换代码:调整PEM首尾标签,代码示例:
byte[] certBytes = Enumerable.Range(0, certHex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(certHex.Substring(x, 2), 16)) .ToArray(); string certPem = "-----BEGIN PUBLIC KEY-----\n" + Convert.ToBase64String(certBytes, Base64FormattingOptions.InsertLineBreaks) .TrimEnd() + "\n-----END PUBLIC KEY-----\n";
- 正确加载公钥:修正后的PEM可被
RSA.ImportFromPem正确识别,无需手动拆分指数和模数(SubjectPublicKeyInfo已包含算法标识和完整公钥结构)。 - X509Certificate2加载问题说明:该类用于加载完整的X.509证书,而你只有公钥数据,因此不能用它加载,直接使用
RSA类处理公钥即可。
内容的提问来源于stack exchange,提问作者Nimrod
相关产品推荐
相关产品推荐

