我已经生成了一份 CSR,并对其进行了签名。我仍然拥有用于创建 CSR 的私钥,并且我想将该证书与该私钥一起存储在 Windows CertStores 中。
我衡量成功的标准是:
当我在 CertStore 中查看证书时,它被标记为具有私钥。具体来说,它在证书图标的左上角有一个小的“密钥”子图标,如果你打开证书,它会在 ValidDates 信息下显示“你有一个与此证书相对应的私钥”。
我们最初认为这.CopyWithPrivateKey(RSA key)
会为我们做到这一点,但它似乎并不能单独工作。我们还需要设置一些 keyStorage 标志,但我们只能.Export()
通过将 cert放入byte[]
数组然后使用另一个构造函数调用“导入”它来做到这一点。
我尝试了很多变体,这是唯一有效的事件序列:
public void InstallCertOnNonUiThread(byte[] certificateDataFromCsrResponse, RSA privateKeyUsedToGenerateCsr)
{
var keyStorageFlags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;
var originalCert = new X509Certificate2(certificateDataFromCsrResponse);
var exportOfOriginalCert = originalCert.Export(X509ContentType.Pkcs12);
var withFlagsCert = new X509Certificate2(certificateDataFromCsrResponse, (SecureString)null, keyStorageFlags);
var exportOfWithFlagsCert = withFlagsCert.Export(X509ContentType.Pkcs12);
var copiedWithPKCert = originalCert.CopyWithPrivateKey(privateKeyUsedToGenerateCsr);
var exportOfCopiedWithPkCert = copiedWithPKCert.Export(X509ContentType.Pkcs12);
var withFlagsReimportOfOriginal = new X509Certificate2(exportOfOriginalCert, (SecureString)null, keyStorageFlags);
var withFlagsReimportOfWithFlags = new X509Certificate2(exportOfWithFlagsCert, (SecureString)null, keyStorageFlags);
var withFlagsReimportOfCopiedWithPK = new X509Certificate2(exportOfCopiedWithPkCert, (SecureString)null, keyStorageFlags);
InstallCertInStore(StoreLocation.LocalMachine, originalCert); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsCert); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, copiedWithPKCert); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfOriginal); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfWithFlags); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfCopiedWithPK);// This one works. Cert has key icon, and text "You have a private key that corresponds to this certificate"
}
private static void InstallCertInStore(StoreLocation location, X509Certificate2 newCert)
{
using (var store = new X509Store(StoreName.My, location))
{
store.Open(OpenFlags.ReadWrite);
store.Add(newCert);
}
}
因此,我执行此操作的最终代码如下所示:
public Task<bool> InstallCertOnNonUiThread(byte[] certificateDataFromCsrResponse, RSA privateKeyUsedToGenerateCsr, string orgId)
{
var keyStorageFlags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;
var originalCert = new X509Certificate2(certificateDataFromCsrResponse);
var copiedWithPKCert = originalCert.CopyWithPrivateKey(privateKeyUsedToGenerateCsr);
var exportOfCopiedWithPkCert = copiedWithPKCert.Export(X509ContentType.Pkcs12);
var withFlagsReimportOfCopiedWithPK = new X509Certificate2(exportOfCopiedWithPkCert, (SecureString)null, keyStorageFlags);
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfCopiedWithPK);// This one works. Cert has key icon, and text "You have a private key that corresponds to this certificate"
return Task.FromResult(true);
}
最后一个选项确实有效,但似乎比应该需要的步骤多得多,这表明我将要定义自己的扩展方法:.ActuallyCopyWithPrivateKey
,以替换该方法的 .NET 框架版本。这似乎是错误的。
有没有更好的方法来实现这一点,或者它真的需要所有 4 个步骤。