当前位置: 首页 > 知识库问答 >
问题:

如何在.NET标准2.0/Core 2.1中使用PrivateKey创建X509Certificate2?

葛承教
2023-03-14
private static X509Certificate2 CreateCertificate(string subject, DateTimeOffset notBefore, DataTimeOffset notAfter, string issuer, AsymmetricKeyParamter issuerPrivateKey)
{
        // Setup
        X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
        SecureRandom random = new SecureRandom(new CryptoApiRandomGenerator());

        RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(new KeyGenerationParameters(random, KeyStrength));

        // Randomly generate a serial number
        BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
        certGenerator.SetSerialNumber(serialNumber);

        // Set the issuer and subject names
        X509Name issuerName = new X509Name(issuer);
        X509Name subjectName = new X509Name(subject);
        certGenerator.SetIssuerDN(issuerName);
        certGenerator.SetSubjectDN(subjectName);

        // Set the validity period
        certGenerator.SetNotBefore(notBefore.UtcDateTime);
        certGenerator.SetNotAfter(notAfter.UtcDateTime);

        // Randomly generate the public key
        AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
        certGenerator.SetPublicKey(subjectKeyPair.Public);

        // Generate the signed certificate
        ISignatureFactory signatureFactory = new Asn1SignatureFactory(SHA256RSASignatureAlgorithm, issuerPrivateKey ?? subjectKeyPair.Private, random);
        X509Certificate2 certificate = new X509Certificate2(certGenerator.Generate(signatureFactory).GetEncoded());

        // Include the private key with the response
        // ERROR HERE!
        certificate.PrivateKey = DotNetUtilities.ToRSA(subjectKeyPair.Private as RsaPrivateCrtKeyParameters);

        return certificate;
}

如何在.NET Standard 2.0中以与.NET Core兼容的方式创建具有私钥的X509Certificate2

共有1个答案

秦鸿羽
2023-03-14

经过大量挖掘,我找到的唯一解决方案是将证书转换为PKCS12格式的字节数组,附加私钥,然后将其读回X509Certificate2对象。它糟透了,但根据我在.NET Core中所知,您可以通过私钥获得一个密钥的唯一方法是调用CopyWithPrivateKey(如问题中所述,在.NET Standard 2.0中不可用),或者加载包含私钥的PKCS12数据。下面的代码可以做到这一点:

    private static X509Certificate2 AddPrivateKeyPlatformIndependent(Org.BouncyCastle.X509.X509Certificate bouncyCastleCert, AsymmetricKeyParameter privateKey)
    {
        string alias = bouncyCastleCert.SubjectDN.ToString();
        Pkcs12Store store = new Pkcs12StoreBuilder().Build();

        X509CertificateEntry certEntry = new X509CertificateEntry(bouncyCastleCert);
        store.SetCertificateEntry(alias, certEntry);

        // TODO: This needs extra logic to support a certificate chain
        AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(privateKey);
        store.SetKeyEntry(alias, keyEntry, new X509CertificateEntry[] { certEntry });

        byte[] certificateData;
        string password = GenerateRandomString();
        using (MemoryStream memoryStream = new MemoryStream())
        {
            store.Save(memoryStream, password.ToCharArray(), new SecureRandom());
            memoryStream.Flush();
            certificateData = memoryStream.ToArray();
        }

        return new X509Certificate2(certificateData, password, X509KeyStorageFlags.Exportable);
    }

使用它来代替问题代码中的最后两行,并且不是使用CertGenerator创建X509Certificate2,而是使用它创建等效的Bouncy Castle类型来传递给它:org.bouncyCastle.x509.x509Certificate bouncyCastleCert=CertGenerator.Generate(signatureFactory);

由于关于Bouncy Castle和.NET证书的文档充其量是稀疏的,下面是我在此过程中发现的一些怪癖:

>

  • PKCS12容器中证书项和密钥项的别名必须相同。否则,您将在尝试使用私钥时得到一个“keyset不存在”异常。

    加载字节数组时必须使用X509KeyStorageFlags.Exportable,否则可能会出现“密钥在指定状态下使用无效”异常,具体取决于证书的使用方式。这也意味着您必须提供密码,因为没有密码就不会重载,但是您可以使用任何旧字符串,因为它是临时密码。

  •  类似资料:
    • 我刚刚使用创建了一个新项目。我的Google-foo可能会让我失望,但我没有找到与我的答案相关的任何内容(如果我错过了一些明显的东西,请链接到另一个SO答案或相关文档)。 如果我想确保此新项目符合 .NET 标准 2.0,我现在该怎么办?

    • 类库定义了可以从任何应用程序调用的类型和方法。 使用.NET Core开发的类库支持.NET标准库,该标准库允许您的库由任何支持该版本的.NET标准库的.NET平台调用。 当完成类库时,可以决定是将其作为第三方组件来分发,还是要将其作为与一个或多个应用程序捆绑在一起的组件进行包含。 现在开始在控制台应用程序中添加一个类库项目(以前创建的FirstApp项目为基础); 右键单击解决方案资源管理器 ,

    • 使用。NET核心IoC容器注入工厂,该方法所做的是从工厂创建一个新客户机: 然后使用客户机从REST服务获取数据:

    • 有没有一种方法可以轻松地将面向.NETCore2.0的类库转换为.NET标准? 如果我理解正确,如果有人想在针对不同.NET框架(例如.NET Framework,.NET Core,Xamarin等)的项目中最大限度地提高类库的可重用性,那么以.NET Standard为目标的更好主意 - 前提是所有必需的API都可以在将要定位的.NET Standard版本中提供。 这就是我想将类库从. NE

    • 只是一个简单的问题。 我一直在网上寻找支持,以创建标准连接帐户与颤振,但我仍然遇到以下问题: \我应该在我的字段中放什么在我的方法中?根据留档,它是: 但它是一款移动应用?所以我有点困惑,我应该把什么放在那里。

    • 本文向大家介绍如何使用JavaFX创建标签?,包括了如何使用JavaFX创建标签?的使用技巧和注意事项,需要的朋友参考一下 现场演示 -> 输出结果