我已经为测试目的创建了一个自签名证书(pfx
)。
我可以通过以下方式导出ist公钥:
X509Certificate2 cer = new X509Certificate2();
X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificateCollection = store.Certificates.Find(...);
var cert = certificateCollection[0] ;
Console.WriteLine(Convert.ToBase64String(cert.Export( X509ContentType.Cert ), Base64FormattingOptions.InsertLineBreaks));
结果:
MIIDFTCCAf2gAw...........eFUpBB9C0/UNRmD7EAg==
这与openssl
命令一致:
$ openssl pkcs12 -in domain.name.pfx -clcerts -nokeys -out domain.name.crt
结果:
-----BEGIN CERTIFICATE-----
MIIDFTCCAf2gAw........9C0/UNRmD7EAg==
-----END CERTIFICATE-----
但是,当我通过C#导出私有键时:
Convert.ToBase64String(cert.Export( X509ContentType.Pfx ), Base64FormattingOptions.InsertLineBreaks)
我明白了:
MIIDFTCCAf2gAw............OVeFUpBB9C0/UNRmD7EAg==
使用openssl
命令:
$ openssl pkcs12 -in domain.name.pfx -nocerts -nodes -out domain.name.key
我明白了:
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w.........6HNjF2h7uuFdvbH2VAVg=
-----END PRIVATE KEY-----
问题:
为什么我在私钥中得到不同的结果?我如何修复我的C#代码以产生与openssl结果相同的结果?
(注意 - 我不是在讨论-----begin/end keys-----
边界,而是实际值。
其他信息,the PFX file
答案 0 :(得分:1)
为什么我在私钥中得到不同的结果?
你正试图做两件事。使用openssl,您使用的是包含私钥和证书的pfx文件。在c#中,您使用了一些带有私钥的证书表示,并且您正在导出到pfx文件!
我如何修复我的C#代码以产生与openssl结果相同的结果?
C#没有友好的功能,只能从X509Certificate2导出私钥(以类似openssl的方式)。正如@ darksquirell42在评论中提到的那样,您可以使用X509Certificate2.PrivateKey
属性,然后将其转换为RSACryptoServiceProvider
并执行ToXmlString(true)
。但是这将为您提供xml结构中的私钥参数。然后你必须采用每个参数并构造一个ASN.1结构PKCS#1或(更好的恕我直言)PKCS#8。但是C#默认没有友好的方法来处理ASN.1对象。
或者你可以使用一些加密库来为你做这样的事情,比如BouncyCastle。来自BouncyCastle的This method可能会有所帮助。
答案 1 :(得分:1)
X509ContentType.Cert
表示相同,因为证书是静态结构。如果你在一个循环中导出它,你将总是得到相同的答案。
X509ContentType.Pfx
表示不同,因为PFX结构中存在随机盐。每个证书一个,每个私钥一个,最后一个。如果在循环中将相同的公共+私有对导出为PFX,则每次都会有所不同(288位随机数据)。
base64数据的结尾是不同的,因为它包含最后一个盐和其余数据的MAC(包括加密的证书盐和加密的密钥盐)。它还包含一个整数工作因子,Windows选择为2000,OpenSSL选择为2048;进一步区分OpenSSL和Windows导出。
所以你看到的是设计。如果您需要稳定的出口,您将不得不做其他事情。如果你只是担心它们会有所不同,那几乎可以肯定。