我正在尝试使用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中会引发相同的错误。
答案 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