C#将证书和密钥(PFX)导入CNG / KSP

时间:2018-07-25 15:11:25

标签: c# windows certificate x509certificate pkcs#12

我正在尝试使用KSP存储证书/密钥(PFX)到Windows证书存储中。其背后的想法是能够使用自定义的KSP,即使现在我只是使用默认的KSP。

使用CNG将密钥存储到KSP中是“容易”的部分,这是对我有用的代码:

X509Certificate2 cert = new X509Certificate2(@"c:\temp\test.pfx", "test123", X509KeyStorageFlags.Exportable);
RSACng rsaCNG = new RSACng();
rsaCNG.FromXmlString(cert.GetRSAPrivateKey().ToXmlString(true));
var keyData = rsaCNG.Key.Export(CngKeyBlobFormat.GenericPrivateBlob);
var keyParams = new CngKeyCreationParameters
{
    ExportPolicy = CngExportPolicies.None,
    KeyCreationOptions = CngKeyCreationOptions.MachineKey,
    Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider
};
keyParams.Parameters.Add(new CngProperty(CngKeyBlobFormat.GenericPrivateBlob.Format, keyData, CngPropertyOptions.None));
var key = CngKey.Create(CngAlgorithm.Rsa, "testKey", keyParams);

但是,我随后无法将此密钥与证书关联,以便将证书正确存储到Windows存储中。以下代码:

rsaCNG = new RSACng(key);
X509Certificate2 certOnly = new X509Certificate2(cert.Export(X509ContentType.Cert));
certOnly.PrivateKey = rsaCNG;
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(certOnly);
store.Close();

失败,但发生例外:Only asymmetric keys that implement ICspAsymmetricAlgorithm are supported.certOnly.PrivateKey = rsaCNG行。

有人知道该怎么做吗?我正在使用.NET Framework 4.6.2,并且在可能的情况下希望避免P / Invoke。而且我可以根据需要升级到.NET Framework 4.7.X,尽管代码在4.7.2中会引发相同的错误。

2 个答案:

答案 0 :(得分:0)

使用4.7.2中的CopyWithPrivateKey扩展方法,它可以理解CAPI和CNG密钥。

// certWithKey understands it has a persisted key reference if rsaCNG's key is
// a named key, so adding it to the store and reading it back will work.
X509Certificate2 certWithKey = certOnly.CopyWithPrivateKey(rsaCNG);
...
store.Add(certWithKey);
...

答案 1 :(得分:0)

尽管bartonjs的回答对于Microsoft软件密钥存储提供程序效果很好,但对于Microsoft平台密钥存储提供程序和机器密钥却失败,这是由于PKI Guy已经指出了a bug in the KSP or .NET(导入的密钥的IsMachineKey为false )。

有一种变通办法适用于平台密钥存储提供程序,甚至适用于机器密钥:https://github.com/glueckkanja-pki/TPMImport