サードパーティのサービス プロバイダから共有された証明書の秘密キーを読み取ろうとしています。これを使用して XML を暗号化してからネットワーク経由で送信できます。私は C# でプログラムでこれを行っていますが、これはアクセス許可または構成ミスの問題だと思うので、最も関連性が高いと思われる事実に焦点を当てます。
- この問題はコードに関連しているとは思いません。私のコードは他のコンピューターで動作し、この問題は Microsoft のサンプル コードに影響します。
- 証明書は PFX ファイルとして提供されており、テスト目的のためだけのものであるため、ダミーの証明機関も含まれています。
- MMC.exe を使用して、証明書をローカル マシンの個人用ストアにインポートしてから、関連するすべてのアカウントに秘密キーのアクセス許可を付与し、証明機関を信頼されたルート証明機関にドラッグ アンド ドロップします。
- C# を使用して、(拇印で識別される) 証明書を読み込み、
X509Certificate2.HasPrivateKey
. ただし、キーを読み取ろうとするとエラーが発生します。.NET ではCryptographicException
、プロパティにアクセスしようとすると、「無効なプロバイダ タイプが指定されました」というメッセージがスローされますX509Certificate2.PrivateKey
。Win32 では、メソッドを呼び出すとCryptAcquireCertificatePrivateKey
、同等の HRESULT が返されますNTE_BAD_PROV_TYPE
。 - これは、Microsoft 独自の 2 つのコード サンプルを使用して証明書の秘密キーを読み取るときに発生する例外と同じです。
- ローカル マシンではなく、現在のユーザーの同等のストアに同じ証明書をインストールすると、秘密鍵を正常に読み込むことができます。
- 私は Windows 8.1 をローカル管理者権限で使用しており、通常モードと昇格モードの両方でコードを実行しようとしました。Windows 7 と Windows 8 の同僚は、同じ証明書のローカル マシン ストアからキーを読み込むことができました。
- 同じストアの場所にある自己署名 IIS テスト証明書の秘密キーを正常に読み取ることができます。
- 既に .NET 4.5 をターゲットにしています (このエラーは、フレームワークの一部の古いバージョンで報告されています)。
- これは証明書テンプレートの問題ではないと思います。ローカル マシンと現在のユーザー ストアの両方に等しく影響すると予想されるからです。
同僚とは異なり、IIS マネージャーを使用したり、同じ発行者からの古い証明書を含めたりするなど、さまざまな方法で証明書のアンインストールと再インストールを何度も試みました。MMC に古い証明書または重複した証明書の痕跡が見当たりません。しかし、同じサイズの秘密鍵ファイルが多数あります。最終書き込み時間に基づいて、さまざまなインストール試行の後に取り残されているに違いありません。これらは、それぞれローカル マシンと現在のユーザー ストアの次の場所にあります。
c:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
c:\Users\\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-[残りのユーザー ID]
それで、誰でもアドバイスしてもらえますか:
- MMC を使用して証明書をアンインストールし、孤立した秘密鍵のように見えるすべてのファイルを削除してから、証明書を再インストールして再試行することをお勧めします。
- 手動で削除する必要がある他のファイルはありますか?
- 他に試してみるべきことはありますか?
更新 - 秘密鍵を読み取る試みを示すコード サンプルを追加しました。
static void Main()
{
// Exception occurs when trying to read the private key after loading certificate from here:
X509Store store = new X509Store("MY", StoreLocation.LocalMachine);
// Exception does not occur if certificate was installed to, and loaded from, here:
//X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.MultiSelection);
Console.WriteLine("Number of certificates: {0}{1}", scollection.Count, Environment.NewLine);
foreach (X509Certificate2 x509 in scollection)
{
try
{
Console.WriteLine("Private Key: {0}", x509.HasPrivateKey ? x509.PrivateKey.ToXmlString(false) : "[N/A]");
x509.Reset();
}
catch (CryptographicException ex)
{
Console.WriteLine(ex.Message);
}
}
store.Close();
Console.ReadLine();
}