我尝试使用 dot-net 生成 X509Certificate2 密钥对,但缺少私钥

I try to generate a X509Certificate2 key pair with dot-net but private key is missing

我尝试使用 dot-net 创建私有-public 密钥对并将其安装在本地密钥库中。当未使用 public 密钥安装私钥时我感到很困惑,然后我注意到尽管证书的 HasPrivateKey 属性 设置为 true 实际 PrivateKey 属性 是 null。如何将私有密钥和 public 密钥都添加到 windows 密钥库?稍后需要证书进行端口绑定。

我目前的代码基本上是这样的:

public static X509Certificate2 CreateSelfSigned(string issuer="", string firendly_name = "")
{
using (var key = RSA.Create(4096))
{
    var req = new CertificateRequest(
        $"CN={issuer}",
        key,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1);
    
    req.CertificateExtensions.Add(
        new X509BasicConstraintsExtension(true, false, 0, true));

    req.CertificateExtensions.Add(
        new X509EnhancedKeyUsageExtension(
            new OidCollection
            {
                // Server Authentifikation
                new Oid("1.3.6.1.5.5.7.3.2"),
                // Client Authentifikation
                new Oid("1.3.6.1.5.5.7.3.1")
            },
            true));

    req.CertificateExtensions.Add(
        new X509SubjectKeyIdentifierExtension(req.PublicKey, false));


    var cert = req.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1),
        DateTimeOffset.UtcNow.AddYears(30));
    cert.FriendlyName = firendly_name;


    using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
    {
        store.Open(OpenFlags.ReadWrite);
        store.Add(cert);
        store.Close();
    }

}
}

我已经在互联网上进行了搜索,但找不到适合我的解决方案。好几个小时都在为这个问题绞尽脑汁。该程序是一种安装程序类型,以前称为 PowerShell 以创建一个自签名证书,该证书只能在一半时间内工作,而且非常脏。我仅限于 dot-net 4.7.2,由于项目限制不能太依赖外部库。

我 运行 不久前遇到了类似的问题,试图从代码中自动为 docker 容器将证书添加到商店。

我使用的解决方案是使用 OpenSSL 工具创建 self-certificate 并将其保存在项目内的文件夹中。注意:我创建了一个 pfx 证书,以便在证书中包含私钥。

所以,我有如下代码

using (X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser, OpenFlags.ReadWrite)) {

store.Add(new X509Certificate2("path-to-certificate/certificate-name.pfx", "certificatePassword"));

}

注意 2:“StoreName.Root”和“StoreLocation.CurrentUser”将根据您要保存证书的商店而有所不同。

希望此解决方案对您有用!

The HasPrivateKey property set to true the actual PrivateKey property is null

您不应该信任或使用 PrivateKey 属性,它对于 ECDSA/ECDH/DH-based 证书始终为空,对于 RSA 和 DSA 也可以为空(如您所见)。 GetRSAPrivateKey() 方法(和其他方法,针对不同的算法)是更好的答案。

How do I get both, private and public key to be added to the windows key store?

问题是 CertificateRequest 将密钥 as-is 绑定到证书。您有一个临时密钥(由 RSA.Create(4096) 创建),因此该证书与临时密钥相关联。当您将它添加到商店时,临时密钥就会被遗忘。

您可以更改密钥创建以创建命名的 CNG 密钥,或者仅将证书导出为 PFX,re-import 使用 PersistKeySet,然后将其添加到存储中。

var cert = req.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1),
    DateTimeOffset.UtcNow.AddYears(30));
cert.FriendlyName = firendly_name;

using (cert)
using (var tmpCert = new X509Certificate2(cert.Export(X509ContentType.Pfx), "", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet))
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
    store.Open(OpenFlags.ReadWrite);
    store.Add(tmpCert);
    store.Close();
}