【问题标题】:.NET 5 fails to export letsencrypt certificate private key.NET 5 无法导出 letencrypt 证书私钥
【发布时间】:2021-03-08 20:48:25
【问题描述】:

我已经生成了让我们加密存储在LocalMachine\My 中的证书。邮件服务器必须每 90 天更新一次证书。我的程序应该每 30 天获取一次有效证书、导出密钥和重启服务。

我在导出私钥时遇到问题。让我们加密证书不受密码保护。

我的错误:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The requested operation is not supported. at System.Security.Cryptography.CngKey.Export(CngKeyBlobFormat format) at 
System.Security.Cryptography.RSACng.ExportKeyBlob(Boolean includePrivateParameters) at 
System.Security.Cryptography.RSACng.ExportParameters(Boolean includePrivateParameters) at 
System.Security.Cryptography.RSA.WritePkcs1PrivateKey() at 
System.Security.Cryptography.RSA.ExportRSAPrivateKey()

代码:

try
{
    using X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

    try
    {
        store.Open(OpenFlags.OpenExistingOnly);

        X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "my.domain.name", true);

        X509Certificate2 certificate = null;

        foreach(X509Certificate2 item in collection)
        {
            if (certificate is null)
                certificate = item;
            else if (item.NotAfter > certificate.NotAfter)
                certificate = item;
        }

        if(certificate is null)
        {
            logger.LogError($"Certificate not found.");

            return;
        }
                    

        byte[] certificateBytes = certificate.RawData;
        char[] certificatePem = PemEncoding.Write("CERTIFICATE", certificateBytes);

        RSA key = certificate.GetRSAPrivateKey();

        byte[] privKeyBytes = key.ExportRSAPrivateKey(); //key.ExportPkcs8PrivateKey(); // CRASH
        char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes);

        string privateKey = $"{new string(privKeyPem).Replace("\r\n\n", "\n")}\n";
        string certificateKey = $"{new string(certificatePem).Replace("\r\n\n", "\n")}\n";

        await File.WriteAllTextAsync("mypath\\key.private", privateKey);
        await File.WriteAllTextAsync("mypath\\key.public", certificateKey);

        // service reboot....
    }
    catch (CryptographicException ex)
    {
        logger.LogError($"Certificate error - {ex}");
    }
    finally
    {
        store.Close();
    }
}
catch(Exception ex)
{
    logger.LogError(ex.ToString());
}

程序由在C:\Program Data\Microsoft\Crypto\RSA\MachineKeys拥有读、写、修改、列出权限的用户运行

.net 5.0.3 版

目标操作系统:windows server 2016

【问题讨论】:

    标签: certificate lets-encrypt private-key .net-5


    【解决方案1】:

    这是因为 Windows 中的一个怪癖,其中 CNG 中的私钥有两个可导出概念(明文可导出与加密可导出)。这是一个非常简单的解决方法:

    PbeParameters simplePbe = new PbeParameters(
        PbeEncryptionAlgorithm.TripleDes3KeyPkcs12,
        HashAlgorithmName.SHA1,
        1);
    
    byte[] = key.ExportEncryptedPkcs8PrivateKey("temp", simplePbe);
    
    using (RSA temp = RSA.Create())
    {
        temp.ImportEncryptedPkcs8PrivateKey("temp", exported, out _);
        privKeyBytes = temp.ExportPkcs8PrivateKey();
    }
    
    char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 1970-01-01
      相关资源
      最近更新 更多