3

以下のコードを見ると、 の新しいインスタンスを作成しているだけRSACryptoServiceProviderです。キー コンテナー名は、さまざまなパラメーターに基づいて名前を作成するプロパティから初期化されます。このデモ コードにハードコードされた値を追加しました。

このコードは、Windows 2008 R2 サーバーのインストールで実行されており、キー コンテナー名に対して定数値が返される状態で数か月間動作しています。

数日前にコードが機能しなくなり、以下の例外に直面しています。何ヶ月も使用されていたキー コンテナー名を使用することはできなくなりました。サーバーが再起動され、IIS が再起動されました - 成功しませんでした。キー名を変更して初めて、再び機能し始めました。

なぜこれが起こっているのか、それを修正する方法を誰かが説明できますか? 私が見る限り、このコードは永続オブジェクトを作成しません。再起動後も失敗するのはなぜですか? MSDN (http://msdn.microsoft.com/de-de/library/ca5htw4f.aspx) から、コンストラクター「コンストラクターは、KeyContainerName フィールドを使用して指定されたキー コンテナーを作成または再利用する」ことを読みました。「再利用」とは、何かをどこかにキャッシュしていて、それをしている間にクラッシュして、キャッシュされたバージョンが破損したままになっていることを意味しますか? また、同じキー名が現在も他の多くのマシンで使用されていることに注意してください。どこにも問題はありません。

これはクラッシュしている行です:

using ( RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( this.oCspParameters ) )
{
}

使用される CspParameters は次のとおりです。

private readonly CspParameters oCspParameters = new CspParameters
{
  Flags = CspProviderFlags.UseMachineKeyStore,
};

this.oCspParameters.KeyContainerName = oProfile.KeyName;

そして、それがキー名です:

public string KeyName
{
    get
    {
        return string.Format( "API-{0}-v{1}", "TestClient", "1.0.0.0" );
    }
}

そして最後に例外:

CryptographicException: An internal error occurred.
Service Operation: ISessionService.Identify #f173250b-d7ac-45d5-98ed-7fffcf37d95a
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
4

2 に答える 2

5

私が見る限り、このコードは永続オブジェクトを作成しません

次のコード、キー コンテナーがまだ存在しない場合に作成します。

using ( RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( this.oCspParameters ) ) 
{ 
} 

既存のキーを強制的に使用する場合は、次を指定する必要があります。

cp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore;

「再利用」とは、何かをどこかにキャッシュしていて、それをしている間にクラッシュして、キャッシュされたバージョンが破損したままになっていることを意味しますか?

Microsoft\Crypto\RSA\MachineKeys\フォルダーのサブフォルダーに保存されているキーEnvironment.SpecialFolder.CommonApplicationDataが存在し、アクセス許可がある場合は、そのキーを再利用します。それ以外の場合は、それを作成しようとします。

アクセス許可のないキーがそ​​こにあるのではないでしょうか?

キー コンテナーのファイル名は生成された一意の ID (CspKeyContainerInfo.UniqueKeyContainerName) を使用しますが、ファイルの内容はテキスト エディターで調べることができ、キー コンテナー名はファイルの最初の数文字にあります。

問題のあるファイルを見つけたら、そのアクセス許可を調べて、再作成できるように削除することができます。

コメントから:

そうしないように強制するにはどうすればよいですか、またはコンテナを削除するにはどうすればよいですか?

次のコードを使用して、既存のキー コンテナーを削除できます (必要なアクセス許可がある場合)。

CspParameters cp = new CspParameters();
cp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey | 
                   CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = containerName;

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp))
{
    rsa.PersistKeyInCsp = false;
}

試したことはありませんがPersistKeyInCsp=false、キーを作成するときに設定すると、永続化できなくなる可能性があります。

ただし、上記のいずれも、以前は正常に使用していたキーにアクセスできなくなった理由を説明していません。最も明白な理由はアクセス許可CryptographicExceptionです。アクセスが許可されていないキー コンテナーにアクセスしようとすると、エラー メッセージが表示されることはわかっていますが、"An内部エラーが発生しました。」最初に行うことは、キー コンテナー ファイルの ACL を確認することです。おそらく、キー コンテナーを作成しようとする異なる ID で実行されているアプリケーションの 2 つのインスタンスがあり、ID 1 によって作成されたキー コンテナーは ID 2 からアクセスできません。

最後に、キー コンテナーを保持したくないとおっしゃっているようですが、なぜマシン ストアを使用するのですか?

于 2012-07-04T13:40:46.620 に答える
1

私は最近、別の開発者がローカル マシンでこの問題を解決するのを手伝っているときに、この質問を発見しました。

このシナリオでは、RSA を使用してパスワードを暗号化していました。問題のコードは、アプリケーションで何年も機能していました。突然、あるRSACryptoServiceProvider開発者のマシンでコンストラクターにエラーが発生し始めました。メッセージは、あいまいで恐ろしい「キーは指定された状態での使用には無効です。

上記のジョーの回答から、次のような場所にキーが保存されていることがわかりました。

C:\Users\<user name>\AppData\Roaming\Microsoft\Crypto\RSA\

キー ファイルを notepad++ で開くと、ファイルの 1 つの上部でキーの名前を見つけることができました。

問題のあるファイルを削除すると、開発者はアプリケーションを再び正常に実行できるようになりました。次にコンストラクターを呼び出したときにファイルが再生成されました。

何が起こったのかはまだわかりませんが、元のキー ファイルが何らかの形で破損したようです。

于 2015-08-14T18:30:33.440 に答える