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

问题描述:

我已创建一个自签名证书(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结果相同的结果?

(NB - 我不是在谈论-----begin/end keys----- boundries,但实际值

其他信息,the PFX file

+0

当你跳过openssl参数“-nodes”并实际提供相同的加密密码时会发生什么? – DarkSquirrel42

+0

@ DarkSquirrel42我得到一个错误https://i.stack.imgur.com/joj8y.png –

+0

ok ... openssl的密码最少有4个字符...你可以在错误信息中看到... – DarkSquirrel42

X509ContentType.Cert表示是相同的,因为证书是静态结构。如果你在一个循环中导出它,你总会得到相同的答案。

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

base64数据的结尾是不同的,因为它包含最后一个salt和其余数据上的MAC(包括加密的cert盐和加密的关键盐)。它还包含一个整数工作因子,Windows选择2000,OpenSSL选择2048;进一步区分OpenSSL和Windows导出。

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

+0

这些输出是不同的,因为一个是私钥,另一个是PFX。不管盐是什么。 openssl导出中没有盐。 – pepo

为什么我得到的私钥不同的结果

你正在尝试做两件独立的事情,在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会很有帮助。

+0

现在我得到了不同的结果。 https://i.stack.imgur.com/CJFiF.png –

+0

@Royi您可以取消base64这两个私钥,并使用ASN.1编辑器查看有什么不同?可能是一个是PKCS#1,另一个是PKCS#8。 – pepo