PrivateKey抛出了System.Security.Cryptography.CryptographicException类型的异常

时间:2017-07-11 18:29:39

标签: c# digital-certificate x509certificate2

我尝试使用以下代码使用自签名证书:

X509Certificate2 cert = ToCertificate("CN=localhost");


public static X509Certificate2 ToCertificate(this string subjectName,
                                                StoreName name = StoreName.My,
                                                StoreLocation location = StoreLocation.LocalMachine
                                                )
    {
        X509Store store = new X509Store(name, location);

        store.Open(OpenFlags.ReadOnly);

        try
        {
            var cert = store.Certificates.OfType<X509Certificate2>().FirstOrDefault(c => c.Subject.Equals(subjectName, StringComparison.OrdinalIgnoreCase));

            return cert != null ? new X509Certificate2(cert) : null;
        }
        catch (Exception)
        {

            throw;
        }
        finally
        {
            store.Certificates.OfType<X509Certificate2>().ToList().ForEach(c => c.Reset());
            store.Close();
        }
    }

我收到以下异常:

PrivateKey = 'cert.PrivateKey' threw an exception of type 'System.Security.Cryptography.CryptographicException'

enter image description here

我尝试this fixthis fix

但仍有问题!

4 个答案:

答案 0 :(得分:3)

如果要调试应用程序,请尝试以管理员身份打开Visual Studio。它为我解决了这个问题。

答案 1 :(得分:2)

听起来您的证书使用CNG密钥存储来存储私钥。在这种情况下,PrivateKey属性将在尝试访问该属性时抛出此异常。

为了正确访问密钥,您必须使用扩展方法来访问密钥:https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2(v=vs.110).aspx#Extension方法

此外,在访问任何私钥存储类型(传统(CSP)或CNG)时,首选这些扩展方法。也就是说,不要直接访问PrivateKeyPublicKey属性,而是通过这些方法访问它们。

答案 2 :(得分:1)

davidchristiansen说:

  

什么是CNG钥匙?   Windows中的证书使用存储提供程序存储。 Windows有两个这些提供程序,它们不兼容。旧式“加密服务提供商”或简称CSP和新款“Cryptography API:Next Generation”或CNG。 CNG提供商自Windows Vista以来一直存在,虽然它更安全,更易于使用,但软件的许多方面仍然与CNG提供商不兼容。这似乎也包括.NET Framework。

     

可能的解决方法可能是直接使用CryptoAPI / CNG API来处理CNG密钥。但是,如果我们想要一个更容易理解CNG的纯粹.NET解决方案,我们需要找到另一个解决方案(详情请遵循!)。

我按照以下帖子进行转换,将我的证书密钥从CNG转换为RSA。它有效!

http://blog.davidchristiansen.com/2016/05/521/

博客的步骤:

  
      
  1. 从PFX中提取公钥和完整证书链   文件
  2.   
  3. 提取CNG私钥
  4.   
  5. 将私钥转换为RSA格式
  6.   
  7. 将具有RSA私钥的公钥合并到新的PFX文件
  8.         

    更改应用程序以使用刚创建的新PFX后,   你会发现你的问题已经解决了。

         

    现在让我们看看如何使用OpenSSL(Get OpenSSL)执行这些步骤   对于Windows从这里)

         
        
    1. 从PFX文件中提取公钥和完整证书链
    2.         

      OpenSSL pkcs12 -in“yourcertificate.pfx”-nokeys -out   “yourcertificate.cer” - passin“pass:myreallystrongpassword”

           
          
      1. 提取CNG私钥
      2.         

        OpenSSL pkcs12 -in“yourcertificate.pfx”-nocerts -out   “yourcertificate.pem”-passin“pass:myreallystrongpassword”-passout   “通:myreallystrongpassword”

             
            
        1. 将私钥转换为RSA格式
        2.         

          OpenSSL rsa -inform PEM -in“yourcertificate.pem”-out   “yourcertificate.rsa”-passin“pass:myreallystrongpassword”-passout   “通:myreallystrongpassword”

               
              
          1. 将具有RSA私钥的公钥合并到新的PFX文件
          2.         

            OpenSSL pkcs12 -export -in“yourcertificate.cer”-inkey   “yourcertificate.rsa”-out“yourcertificate-converted.pfx”-passin   “pass:myreallystrongpassword”-passout“pass:myreallystrongpassword”

答案 3 :(得分:1)

该程序在IIS Express上运行,使用您的凭据访问证书,而在IIS上,则使用池标识的凭据。您可以轻松地检查证书ACL,以查看允许或不允许的人。

请按照以下步骤操作:

  1. 检查您的网站使用的应用程序池

打开Internet信息服务管理器,在左侧的“连接”树中选择“站点”。在中间面板中选择您的站点,然后单击右侧面板上“操作”下的“基本设置”。

  1. 检查应用程序池使用的身份

在左侧的“连接”树中选择“应用程序池”,然后在中间面板中找到标识。可能是“网络服务”。

  1. 将应用程序池所使用身份的读取权限添加到您的证书中

打开Microsoft管理控制台(mmc),添加本地计算机帐户的证书管理单元,然后在“个人证书”下找到您的证书。打开其上下文菜单,“所有任务”和“管理私钥...”。单击“添加”,输入标识(“网络服务”),然后单击“检查名称”和“确定”。在“权限”下,仅允许“读取”权限。

您可以阅读以下问题的详细信息:如何授予ASP.NET访问证书存储区中证书私钥的权限?

引用:Certificate private key throws CryptographicException under IIS Web Server