【问题标题】:C# import certificate and key (PFX) into CNG/KSPC# 将证书和密钥 (PFX) 导入 CNG/KSP
【发布时间】:2019-01-02 11:24:51
【问题描述】:

我正在尝试将证书/密钥 (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 中会引发相同的错误。

【问题讨论】:

    标签: c# windows certificate x509certificate pkcs#12


    【解决方案1】:

    虽然 bartonjs 的答案适用于 Microsoft 软件密钥存储提供程序,但由于 PKI Guy 已经指出的a bug in the KSP or .NET(导入的密钥的 IsMachineKey 为 false),它对 Microsoft 平台密钥存储提供程序和机器密钥失败。

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

    【讨论】:

      【解决方案2】:

      使用 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);
      ...
      

      【讨论】:

      • 谢谢!它使用默认的 KSP(软件)。但是,当我尝试使用另一个 KSP(例如 Microsoft Platform Crypto Provider)时,您的线路会因Keyset does not exist(HRESULT 2146893802) 而失败。
      • @PKIGuy 奇怪。如果您可以提供重现步骤,请report a bug.
      • 确定:在我的原始代码中,将 CngProvider.MicrosoftSoftwareKeyStorageProvider 替换为 new CngProvider("Microsoft Platform Crypto Provider"),然后使用您的代码。当然,您的机器上需要一个有效的 TPM。
      • 抱歉,忘记提及生成的应用程序是从具有提升权限的 cmd 启动的
      • 顺便说一句,将ExportPolicy 更改为CngExportPolicies.AllowArchiving(这对这个KSP 很有意义),将错误更改为The provided key does not match the public key for this certificate (HRESULT -2147024809)。
      猜你喜欢
      • 1970-01-01
      • 2017-02-03
      • 2013-01-02
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2014-03-01
      • 2016-10-26
      • 2012-06-06
      相关资源
      最近更新 更多