12

マシンに証明書がインストールされていて、それを表示すると、「この証明書に対応する秘密鍵があります」というメッセージが表示されますが、コードでその秘密鍵にアクセスしようとすると、null になります。次のコードを使用して証明書を取得します。

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であることです。質問への回答を妨げている私の抽象化に関する情報がさらにある場合は、詳細を提供できます。

4

3 に答える 3

6

ここ で説明されているように、.cerファイル (すべての証明書形式にも適用できると思います) に秘密鍵を含めることはできません。このファイルは公開されているため、セキュリティの観点からは正しく見えます。
しかしX509Certificate2、単なる証明書ではなく、証明書自体やその他のもののコンテナです。それがプロパティを持っている理由PrivateKeyです。コードでこの情報が必要な場合、および秘密鍵ファイル ( .pvk) とパスワードがある場合 -.pfxの代わりにファイルを使用できます.cerpvk2pfxユーティリティを使用して作成できます。

> 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
于 2013-03-23T17:31:34.763 に答える
2

リセットのドキュメントには、証明書のリソースが解放されると記載されています。もちろん、このメソッドは Dispose ではなく Reset と呼ばれるため、後で再び必要になった場合にインスタンスがそれらのリソースを再取得できるはずであるというのは妥当な想定です。残念ながらそうではありません。

GetCertificate の finally ブロックでは、コレクション内のすべての証明書に対して Reset を呼び出します。これには、返すものも含まれます。これにより、役に立たなくなります。

于 2014-03-07T00:25:36.880 に答える