证书的私钥导出为不同的值?

Certificate's private key is exported as a different value?

我创建了一个自签名证书 (pfx) 用于测试目的。

我可以通过以下方式导出 ist public 密钥:

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# 导出 private 密钥时:

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

Why do I get different results in the private keys ?

您正在尝试做两件不同的事情。使用 openssl,您使用的是包含私钥和证书的 pfx 文件。在 c# 中,您正在使用带有私钥的证书的某种表示形式,并且正在导出到 pfx 文件!

And how can I fix my C# code to yield the same result as openssl's result ?

C# 没有只能从 X509Certificate2 导出私钥(以类似 openssl 的方式)的友好函数。正如 @darksquirell42 在评论中提到的,您可以使用 X509Certificate2.PrivateKey 属性,然后将其转换为 RSACryptoServiceProvider 并执行 ToXmlString(true). But this will give you private key parameters in a xml structure. Then you would have to take each parameter and construct an ASN.1 structure PKCS#1 or (IMHO better) PKCS#8。但是 C# 默认没有友好的方法来处理 ASN.1 对象。

或者你可以使用一些加密库来为你做这件事,比如 BouncyCastle。来自 BouncyCastle 的 This method 可能会有所帮助。

X509ContentType.Cert表示相同,因为证书是静态结构。如果您循环导出它,您将始终得到相同的答案。

X509ContentType.Pfx表示不同,因为PFX结构中有随机盐。每个证书一个,每个私钥一个,最后一个。如果您在循环中将相同的 public+私有对作为 PFX 导出,则每次都会不同(288 位随机数据​​)。

base64 数据的末尾是不同的,因为它包含最后一个盐和 MAC 覆盖其余数据(包括加密的证书盐和加密的密钥盐)。它还包含一个整数工作因子,Windows选择为2000,OpenSSL选择为2048;进一步区分 OpenSSL 和 Windows 导出。

所以您看到的是设计使然。如果您需要稳定的出口,您将不得不做其他事情。如果您只是担心它们不同,那几乎可以肯定没问题。