通过代码访问时私钥为空,为什么?

时间:2013-02-07 15:19:31

标签: c# asp.net certificate x509certificate x509certificate2

我的计算机上安装了证书,当我去查看它时,我看到消息“你有一个与此证书对应的私钥”但是,当我尝试在代码中访问该私钥时,它是空值。我使用以下代码获取证书:

var x509Certificate = GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=SomeCert");

其中:

public X509Certificate2 GetCertificate(string storeName, string storeLocation, string subjectName)
{
     var store = new X509Store(getStoreName(storeName), getStoreLocation(storeLocation));
     X509Certificate2Collection certificates = null;
     store.Open(OpenFlags.ReadOnly);

     try
     {
          X509Certificate2 result = null;
          certificates = store.Certificates;
          return getCertificateResult(certificates, subjectName, result);
     }
     finally
     {
          if (certificates != null)
          {
               foreach (var cert in certificates)
               {
                    cert.Reset();
               }
          }
          store.Close();
     }
}

private static X509Certificate2 getCertificateResult(IEnumerable certificates, string subjectName, X509Certificate2 result)
{
     foreach (var cert in certificates.Cast<X509Certificate2>().Where(cert => cert.SubjectName.Name != null && cert.SubjectName.Name.ToLower() == subjectName.ToLower()))
     {
          if (result != null)
          {
             throw new ApplicationException(string.Format("There is more than one certificate found for subject Name {0}", subjectName));
          }
          result = new X509Certificate2(cert);
     }

     if (result == null)
     {
          throw new ApplicationException(string.Format("No certificate was found for subject Name {0}", subjectName));
     }
     return result;
}

我的证书很好,但是当我尝试访问私钥时,请执行以下操作:

x509Certificate.PrivateKey

PrivateKey的值为null。我究竟做错了什么?我需要此值来签署SAML2请求。

注意:我知道我在那里有一些抽象,但关键是我得到了证书(它已找到)但私钥是null。如果有关于我的抽象的更多信息阻止了问题的回答,我可以提供更多细节。

3 个答案:

答案 0 :(得分:6)

正如所描述的那样here .cer文件(我猜它也适用于所有证书格式)不能包含私钥。从安全的角度看它是正确的,因为这个文件是公开的 但是X509Certificate2不仅仅是证书,它还是证书本身和其他东西的容器。这就是为什么它有财产PrivateKey。如果您在代码中需要此信息,并且拥有私钥文件(.pvk)和密码,则可以使用.pfx文件而不是.cer。它可以使用pvk2pfx实用程序:

创建
> MakeCert -r -pe -ss SampleStoreName -n "CN=Sample" Sample.cer -sky exchange -sv Sample.pvk
> pvk2pfx -pvk Sample.pvk -pi SamplePassword -spc Sample.cer -pfx Sample.pfx -f

答案 1 :(得分:2)

重置documentation表示它释放了证书的资源。当然,因为该方法被称为Reset而不是Dispose,所以假设实例应该能够在以后再次需要时重新获取这些资源,这是一个合理的假设。不幸的是,事实并非如此。

在GetCertificate的finally块中,您在集合中的每个证书上调用Reset - 包括您要返回的证书,这使得它无用。

答案 2 :(得分:0)

我知道这个问题已经很久了,但是对于那里的未来读者来说,让我加上我的想法。

对我而言,您获得的证书似乎不包含私钥。商店中的所有证书都没有私钥。当然,您自己的证书将拥有私钥,但其他实体的证书将没有合法的私钥。

在您的代码中,您没有显示您从中获取证书的商店位置。你得到的证书不是你自己的证书吗?