将带有私钥的X509Certificate2导出为字节数组

32

我有一个存储在证书库中的X509Certificate2证书,我想将其导出为一个包含私钥的字节数组。这个证书字节数组必须是这样的,以便当我稍后从字节数组中导入证书时,私钥也会随之导入。

我尝试了很多方法,但没有成功导出带私钥的证书。

X509Store store = new X509Store(StoreLocation.CurrentUser);      

store.Open(OpenFlags.ReadOnly);

X509Certificate2 cert = store.Certificates[1];

byte[] certBytes = cert.GetRawCertData(); // Obviously does not work!

能否成功将带有私钥的证书导出为字节数组?

非常感谢您的帮助。

2个回答

36

X509Certificate2类的Export函数允许您将带有私钥的证书导出为字节数组。

以下代码演示了如何导出带有私钥的证书:

X509Store store = new X509Store(StoreLocation.CurrentUser);

store.Open(OpenFlags.ReadOnly);

X509Certificate2 cert = store.Certificates[1];

// Export the certificate including the private key.
byte[] certBytes = cert.Export(X509ContentType.Pkcs12);

为了保护您导出的证书,请使用以下重载的 Export 函数:

byte[] certBytes = cert.Export(X509ContentType.Pkcs12, "SecurePassword");

BEGIN EDIT

使用以下代码导入证书:

X509Certificate2 certToImport = new X509Certificate2(arr, "SecurePassword");

// To mark it as exportable use the following constructor:
X509Certificate2 certToImport = new X509Certificate2(arr, "SecurePassword", X509KeyStorageFlags.Exportable);
// certToImport.HasPrivateKey must be true here!!

X509Store store2 = new X509Store(StoreName.TrustedPublisher,
                                 StoreLocation.CurrentUser);
store2.Open(OpenFlags.MaxAllowed);

store2.Add(certToImport);
store2.Close();

编辑结束


谢谢你的回答,但我仍然有问题。当我运行你的代码并再次导入它时,HasPrivateKey = false。可能是什么问题? - Erik Larsson
1
@ErikLarsson:我已经更新了我的答案。希望这可以帮到你。在我的机器上,属性HasPrivateKey为true。如果我打开MMC以导出导入的证书,我也能够导出私钥。 - Hans
对于任何找到这个线程的人,请注意,如果您想再次导出它,您需要在导入时将其设置为“可导出”,请参见下一个答案以及https://dev59.com/4Wox5IYBdhLWcg3wNRpj#9373407。 - yoel halb
4
这将导致.NET 4.6.2控制台应用程序抛出System.Security.Cryptography.CryptographicException: 'Key not valid for use in specified state.'异常。 - Eivind Gussiås Løkseth
@EivindGussiåsLøkseth:你在哪里得到这个异常? - Hans
@Hans,我遇到的问题与特定的.NET版本无关。我有一个带有不可导出私钥的pfx文件,这就是代码失败的原因。不幸的是,在发现这个问题后,我找不到我的评论并删除它。 - Eivind Gussiås Løkseth

4

无法获取私钥的一个原因可能是当它最初被添加到CAPI时已被标记为“不可导出”。在这种情况下,我认为没有真正的方法可以将其取出。


3
不,这只意味着你需要更强的技巧。如果它可以使用,就可以出口。 - Joshua
@Joshua,当证书被标记为“不可导出”时,它只能通过操作系统用于签名/解密输入,并且操作系统返回结果。因此,私钥可以使用,但受到保护并且无法导出。 - fjch1997
1
@fjch1997:有时候将调试器附加到lsass。 - Joshua
@Joshua 当您从证书存储中获取证书时,处理私钥的不是托管代码。 - fjch1997
@fjch1997:嗯,当你使用内核调试器时,你更喜欢本地代码。 - Joshua
@Joshua 我快速进行了一次谷歌搜索,发现确实有工具可以窥视内存并检索私钥。对于这一点,我对微软表示不满... - fjch1997

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