簡體   English   中英

RSACryptoServiceProvider(RSACryptoServiceProvider)構造函數在.NET 3.5中因某些鍵名而崩潰

[英]RSACryptoServiceProvider(RSACryptoServiceProvider) constructor crashing in .NET 3.5 for certain key names

如果您看下面的代碼,除了創建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)

據我所知,這段代碼不會創建任何持久對象

以下代碼創建密鑰容器(如果尚不存在):

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

如果要強制使用現有密鑰,則應指定:

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

“重用”是否意味着它正在將內容緩存在某個地方,而同時又崩潰了,現在卡在了一個損壞的緩存版本中?

它將重用存儲在Environment.SpecialFolder.CommonApplicationData文件夾的Microsoft\\Crypto\\RSA\\MachineKeys\\子文件夾中的Microsoft\\Crypto\\RSA\\MachineKeys\\ (如果存在)並且您有權訪問它。 否則它將嘗試創建它。

也許那里有一個您沒有訪問權限的密鑰?

密鑰容器的文件名使用生成的唯一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 ,但我不知道您是否希望得到比“發生了內部錯誤”。 我要做的第一件事是檢查密鑰容器文件上的ACL。 也許您有兩個應用程序實例以不同的身份運行,這些實例嘗試創建密鑰容器-身份2無法訪問由身份1創建的密鑰容器。

最后,正如您似乎建議您不想保留密鑰容器一樣,為什么還要使用計算機存儲?

我最近在幫助另一個開發人員在其本地計算機上解決此問題的同時發現了這個問題。

在我們的方案中,我們使用RSA加密密碼。 有問題的代碼在應用程序中已經使用了多年。 突然, RSACryptoServiceProvider構造函數開始在一個開發人員的計算機上遇到錯誤。 該消息模棱兩可,令人恐懼:“ 密鑰在指定狀態下無效。

從上面喬的答案中,我們發現密鑰存儲在以下位置:

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

通過在notepad ++中打開密鑰文件,我們可以在其中一個文件的頂部找到密鑰的名稱。

刪除有問題的文件可使開發人員再次成功運行應用程序 -下次我們調用構造函數時,將重新生成該文件。

我仍然不確定發生了什么,但是看來原始密鑰文件已以某種方式損壞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM