Kru*_*lur 3 .net c# cryptography rsacryptoserviceprovider
如果您查看下面的代码,它只会创建一个RSACryptoServiceProvider. 密钥容器名称从基于各种参数创建名称的属性初始化。我在此演示代码中添加了硬编码值。
该代码在 Windows 2008 R2 服务器安装上运行,并且已经运行了数月,并为密钥容器名称返回了一个常量值。
几天前,代码停止工作,我们面临以下异常。使用已使用数月的密钥容器名称不再有效。服务器已重新启动,IIS 已重新启动 - 没有成功。只有在更改密钥名称后,它才再次开始工作。
有人可以解释为什么会发生这种情况以及如何解决吗?据我所知,这段代码没有具体化任何持久对象。为什么重启后还是会失败?从 MSDN (http://msdn.microsoft.com/de-de/library/ca5htw4f.aspx) 我读到构造函数“构造函数创建或重用使用 KeyContainerName 字段指定的密钥容器”。“重用”是否意味着它正在某处缓存这些东西,并且在这样做时它崩溃了并且现在被一个损坏的缓存版本卡住了?另请注意,当前许多其他机器上仍在使用相同的密钥名称 - 任何地方都没有问题。
这是崩溃的行:
using ( RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( this.oCspParameters ) )
{
}
Run Code Online (Sandbox Code Playgroud)
这些是使用的 CspParameters:
private readonly CspParameters oCspParameters = new CspParameters
{
Flags = CspProviderFlags.UseMachineKeyStore,
};
this.oCspParameters.KeyContainerName = oProfile.KeyName;
Run Code Online (Sandbox Code Playgroud)
这就是关键名称:
public string KeyName
{
get
{
return string.Format( "API-{0}-v{1}", "TestClient", "1.0.0.0" );
}
}
Run Code Online (Sandbox Code Playgroud)
最后是例外:
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)
Run Code Online (Sandbox Code Playgroud)
据我所知,这段代码没有产生任何持久对象
如果密钥容器不存在,以下代码将创建它:
using ( RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( this.oCspParameters ) )
{
}
Run Code Online (Sandbox Code Playgroud)
如果要强制使用现有密钥,则应指定:
cp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore;
Run Code Online (Sandbox Code Playgroud)
“重用”是否意味着它正在某处缓存这些东西,而在这样做时它崩溃了,现在被一个损坏的缓存版本卡住了?
它将重用存储在Microsoft\Crypto\RSA\MachineKeys\文件夹子文件夹中的密钥Environment.SpecialFolder.CommonApplicationData,如果它存在并且您有权访问它。否则它将尝试创建它。
也许那里有一个您无权访问的密钥?
密钥容器的文件名使用生成的唯一标识(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;
}
Run Code Online (Sandbox Code Playgroud)
我还没有尝试过,但是PersistKeyInCsp=false创建密钥时的设置可能会阻止 if 被持久化。
但是,以上都没有解释为什么您无法再访问以前成功使用的密钥。最明显的原因是权限 - 我知道CryptographicException如果您尝试访问您无权访问的密钥容器,您会得到一个,但我不知道您是否希望收到比“An发生内部错误”。我要做的第一件事是检查密钥容器文件上的 ACL。也许您的应用程序有两个以不同身份运行的实例,它们试图创建密钥容器 - 而身份 2 无法访问由身份 1 创建的密钥容器。
最后,正如您似乎建议您不想保留密钥容器一样,您为什么要使用机器存储?