【问题标题】:I try to generate a X509Certificate2 key pair with dot-net but private key is missing我尝试使用 dot-net 生成 X509Certificate2 密钥对,但缺少私钥
【发布时间】:2020-09-23 00:16:33
【问题描述】:

我尝试使用 dot-net 创建一个私钥-公钥对并将其安装在本地密钥库中。当私钥没有与公钥一起安装时,我感到很困惑,然后我注意到尽管证书将HasPrivateKey 属性设置为true,但实际的PrivateKey 属性是null。如何将私钥和公钥都添加到 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 并且不能非常依赖外部库。

【问题讨论】:

    标签: c# .net windows private-key x509certificate2


    【解决方案1】:

    HasPrivateKey 属性设置为 true 实际 PrivateKey 属性为空

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

    如何将私钥和公钥都添加到 Windows 密钥库中?

    问题在于 CertificateRequest 将密钥按原样绑定到证书。您有一个临时密钥(由RSA.Create(4096) 创建),因此该证书与一个临时密钥相关联。当您将其添加到存储时,临时密钥就会被遗忘。

    您可以更改您的密钥创建以创建一个命名的 CNG 密钥,或者只是将证书导出为 PFX,使用 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();
    }
    

    【讨论】:

      【解决方案2】:

      不久前我遇到了一个类似的问题,我试图将证书从代码中自动添加到 docker 容器的存储中。

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

      所以,我有如下代码

      使用 (X509Store 存储 = 新 X509Store(StoreName.Root, StoreLocation.CurrentUser, OpenFlags.ReadWrite)) {

      store.Add(新 X509Certificate2("证书路径/证书名称.pfx", "证书密码"));

      }

      注意 2:“StoreName.Root”和“StoreLocation.CurrentUser”会因您要保存证书的商店而异。

      希望这个解决方案对您有用!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-26
        • 2014-10-09
        • 1970-01-01
        • 1970-01-01
        • 2018-10-20
        相关资源
        最近更新 更多