簡體   English   中英

如何在 .NET Standard 2.0/Core 2.1 中使用 PrivateKey 創建 X509Certificate2?

[英]How to create X509Certificate2 with PrivateKey in .NET Standard 2.0/Core 2.1?

我們正在生成一些自簽名證書以使用 BouncyCastle 進行測試,但是當我們嘗試向證書添加私鑰時,代碼會引發異常。 這是有問題的代碼:

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 2.1,另一個面向 .NET Framework 4.7.2。 我相信這在 .NET Framework 應用程序中工作正常,但在 .NET Core 應用程序中,我在上面指示的行中收到此消息的異常:

此平台不支持操作。

顯然, 這是 .NET Core 中的預期行為 我知道這個問題中提到的CopyWithPrivateKey方法,理論上我應該使用它。 但是, .NET Standard 2.0 不支持此方法(請注意頁面頂部指示重定向的錯誤)。 此外,由於 .NET Framework 的其他一些依賴項,.NET Framework 應用程序目前無法轉換為 .NET Core。 根據此矩陣,.NET Framework 根本不支持 .NET Standard 2.1,這意味着我無法升級到 .NET Standard 2.1並使用CopyWithPrivateKey

如何以與 .NET Core 兼容的方式在 .NET Standard 2.0 中創建帶有私鑰的X509Certificate2

經過大量挖掘,我找到的唯一解決方案是將證書轉換為 PKCS12 格式的字節數組,附加私鑰,然后將其讀回X509Certificate2對象。 這很糟糕,但據我所知,在 .NET Core 中,您可以使用私鑰獲取私鑰的唯一方法是調用CopyWithPrivateKey (如問題中所述,在 .NET Standard 2.0 中不可用)或加載包含私鑰。 下面的代碼可以做到這一點:

    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創建X509Certificate2certGenerator使用它來創建等效的 Bouncy Castle Type 以傳遞給它: Org.BouncyCastle.X509.X509Certificate bouncyCastleCert = certGenerator.Generate(signatureFactory);


由於有關 Bouncy Castle 和 .NET 證書的文檔充其量很少,因此我在此過程中發現了一些怪癖:

  • PKCS12 容器中證書條目和密鑰條目的別名必須相同。 否則,您將在嘗試使用私鑰時收到“密鑰集不存在”異常。

  • 加載字節數組時必須使用X509KeyStorageFlags.Exportable ,否則根據您使用證書的方式,您可能會收到“密鑰在指定狀態下無效”異常。 這也意味着您必須提供密碼,因為沒有它就不會過載,但您可以使用任何舊字符串,因為它是臨時密碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM