对于某些键名,RSACryptoServiceProvider(RSACryptoServiceProvider)构造函数在.NET 3.5中崩溃 [英] RSACryptoServiceProvider(RSACryptoServiceProvider) constructor crashing in .NET 3.5 for certain key names

查看:129
本文介绍了对于某些键名,RSACryptoServiceProvider(RSACryptoServiceProvider)构造函数在.NET 3.5中崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果您看下面的代码,除了创建RSACryptoServiceProvider的新实例外,它什么都不做. 密钥容器的名称是从一个属性初始化的,该属性会根据各种参数创建一个名称.我已在此演示代码中添加了硬编码值.

If you look at the code below it is doing nothing but creating a new instance of an RSACryptoServiceProvider. The key container name is initialized from a property that creates a name based on various parameters. I have added hardcoded values in this demo code.

该代码在Windows 2008 R2服务器安装上运行,并且已经工作了几个月,并且为密钥容器名称返回了一个恒定值.

The code is running on a Windows 2008 R2 server installation and has worked for months with a constant value being returned for the key container name.

几天前,代码停止工作,我们正面临以下异常. 使用已经使用了几个月的密钥容器名称不再起作用.服务器已重新启动,IIS已重新启动-没有成功.仅在更改了密钥名称后,它才能再次开始工作.

Some days ago the code stopped working and we're facing the exception below. Using the key container name that has been used for months no longer works. The server has been rebooted, IIS has been restarted - no success. Only after changing the key name it has started to work again.

有人可以解释为什么会发生这种情况以及如何解决吗?据我所知,这段代码不会创建任何持久对象.为什么重启后仍然失败?从MSDN(http://msdn.microsoft.com/de-de/library/ca5htw4f.aspx)中,我读到构造函数"构造函数创建或重用使用KeyContainerName字段指定的密钥容器". " reuse "是否表示它正在将内容缓存在某个地方,并且在崩溃的同时现在被损坏的缓存版本所卡住了? 还要注意,相同的密钥名称目前仍在许多其他计算机上使用-在任何地方都没有问题.

Can somebody explain why this is happening and how to fix it? As far as I can see, this code does not crete any persistent objects. Why would it still fail after a reboot? From MSDN (http://msdn.microsoft.com/de-de/library/ca5htw4f.aspx) I read that the constructor "constructor creates or reuses a key container specified using the KeyContainerName field". Does the "reuse" mean, it is caching the stuff somewhere and while doing that it crashed and is now stuck with a corrupt cached version? Also note that the same key name is currently still used on many other machines - no problems anywhere.

这是崩溃的行:

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

这些是所使用的CspParameter:

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)

推荐答案

据我所见,这段代码不会创建任何持久对象

As far as I can see, this code does not crete any persistent objects

以下代码创建密钥容器(如果尚不存在):

The following code will create the key container if it doesn't already exist:

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

如果要强制使用现有密钥,则应指定:

If you want to force use of an existing key, you should specify:

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

重用"是否意味着它正在将内容缓存在某个地方,同时崩溃了,现在卡在了一个损坏的缓存版本中?

Does the "reuse" mean, it is caching the stuff somewhere and while doing that it crashed and is now stuck with a corrupt cached version?

它将重用存储在Environment.SpecialFolder.CommonApplicationData文件夹的Microsoft\Crypto\RSA\MachineKeys\子文件夹中的密钥(如果存在)并且您有权访问它.否则它将尝试创建它.

It will reuse a key stored in the Microsoft\Crypto\RSA\MachineKeys\ subfolder of the Environment.SpecialFolder.CommonApplicationData folder, if it exists and you have permission to access it. Otherwise it will attempt to create it.

也许那里有一个您无权访问的密钥?

Perhaps there is a key there that you don't have permission to access?

密钥容器的文件名使用生成的唯一ID(CspKeyContainerInfo.UniqueKeyContainerName),但是您可以使用文本编辑器检查文件内容,并且密钥容器名位于文件的前几个字符中.

The file names of the key containers use a generated unique id (CspKeyContainerInfo.UniqueKeyContainerName), but you can examine the file contents with a text editor, and the key container name is in the first few characters of the file.

一旦找到了有问题的文件,就可以检查其权限,甚至可以删除它,以便重新创建它.

Once you have located the offending file, you can examine its permissions, and perhaps delete it so it can be recreated.

来自评论:

如何强制其然后不这样做或如何删除该容器?

How can I force it then to NOT do so or how can I delete the container?

使用以下代码完成操作后,可以删除现有的密钥容器(前提是您具有必需的权限):

You can delete a existing key container (provided you have the necessary permissions) when you've finished with it with the following code:

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可以防止持久化.

I haven't tried it, but perhaps setting PersistKeyInCsp=false when creating the key would prevent if from being persisted.

但是,以上内容都无法解释为什么您不再能够访问以前成功使用的密钥.最明显的原因是权限-如果您尝试访问未经授权访问的密钥容器,我知道您会得到一个CryptographicException,但是我不知道您是否期望得到更明确的错误消息而不是发生内部错误".我要做的第一件事是检查密钥容器文件上的ACL.也许您有两个在不同身份下运行的应用程序实例试图创建密钥容器-身份2无法访问由身份1创建的密钥容器.

However none of the above explains why you are no longer able to access a key that you were previously using successfully. The most obvious reason would be permissions - I know you get a CryptographicException if you attempt to access a key container that you're not authorized to access, but I don't know if you would expect to get a more explicit error message than "An internal error occurred". The first thing I'd do would be to check the ACL on the key container file. Perhaps you have two instances of your application running under different identities that attempt to create the key container - and the key container created by identity 1 is not accessible by identity 2.

最后,您似乎建议您不要保留密钥容器,为什么要使用计算机存储?

Finally as you seem to suggest you don't want to persist the key container, why would you use the machine store?

这篇关于对于某些键名,RSACryptoServiceProvider(RSACryptoServiceProvider)构造函数在.NET 3.5中崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆