C# 意外的CryptographicException:密钥集不存在,CryptographicException:访问被拒绝
我们正试图在XP SP2机器(Win7更高版本)上为C#(.net 3.5)应用程序实现这一点 在我们的安装程序(由VS2008创建)中,我们使用C# 意外的CryptographicException:密钥集不存在,CryptographicException:访问被拒绝,c#,.net,security,encryption,installation,C#,.net,Security,Encryption,Installation,我们正试图在XP SP2机器(Win7更高版本)上为C#(.net 3.5)应用程序实现这一点 在我们的安装程序(由VS2008创建)中,我们使用AES密钥和iv加密连接字符串,然后创建RSA密钥对,并将它们存储在MachineKeyStore中。安装程序将使用RSA公钥对AES密钥和iv进行加密,并将加密的密钥和iv与加密的连接字符串一起存储 安装后,我们的应用程序将读取带有加密AES密钥和iv的加密连接字符串,并使用RSA私钥(来自MachineKeyStore)解密AES密钥和iv,然后使
AES
密钥和iv加密连接字符串,然后创建RSA密钥对
,并将它们存储在MachineKeyStore
中。安装程序将使用RSA公钥对AES密钥和iv进行加密,并将加密的密钥和iv与加密的连接字符串一起存储
安装后,我们的应用程序将读取带有加密AES密钥和iv的加密连接字符串,并使用RSA私钥
(来自MachineKeyStore
)解密AES
密钥和iv,然后使用AES
密钥和iv解密连接字符串
对于MachineKeyStore
的容器名称
,安装程序和我们的应用程序共享一个常量字符串
我知道密钥对存储在哪里,所以我可以监视它以查看是否删除、更新或创建了密钥对
我做了一些测试,发现了一些有趣的事情(出乎意料),但不知道为什么会这样。我的用户帐户是管理员帐户
安装程序可以删除由我们的应用程序创建的存储的密钥对
,并立即创建一个具有相同容器名称的新密钥对李>
安装程序可以更新由我们的应用程序创建的密钥对
(不要删除并再次创建,我认为它正在覆盖-但根据文档,这不应该发生)
我们的应用程序无法删除安装程序创建的密钥对:加密异常:密钥集不存在。
当密钥对实际存在时,将发生异常李>
当安装程序创建的密钥对存在时,我们的应用程序无法创建新的密钥对:加密异常:密钥集不存在。
我们的应用程序无法访问安装程序创建的密钥对,
加密异常:访问被拒绝。
在这种情况下会发生。安装程序中的加密使用AES
和RSA公钥
。当应用程序尝试使用存储的私钥
进行解密时,将发生“访问被拒绝
”异常
我们的守则如下:
public static void CreateRSAKeyPair(string keyContainerName)
{
DeleteRSAKeyPair(keyContainerName);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = keyContainerName;
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams))
{
rsa.PersistKeyInCsp = false;
}
}
public static void DeleteRSAKeyPair(string keyContainerName)
{
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = keyContainerName;
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams))
{
rsa.PersistKeyInCsp = false;
try
{
rsa.Clear();
}
catch (CryptographicException ex)
{
Log.logItem(LogType.Exception, "RSA key clear error, can be ignored", "SecurityMgr::DeleteRSAKeyPair()", "CryptographicException msg=" + ex.ToString());
}
}
}
用于解密的访问私钥的代码:
private static byte[] RSADecrypt(byte[] inputData, string keyContainerName)
{
byte[] resultData = null;
try
{
CspParameters cspParams = new CspParameters();
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
cspParams.KeyContainerName = keyContainerName;
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams))
{
//rsaProvider.PersistKeyInCsp = true;
//private key
RSAParameters rsaParams = rsaProvider.ExportParameters(true);
rsaProvider.ImportParameters(rsaParams);
resultData = rsaProvider.Decrypt(inputData, false);
}
}
catch (CryptographicException ex)
{
string msg = "CryptographicException: keyContainerName=" + keyContainerName + "\nmsg=" + ex.ToString();
Log.logItem(LogType.Exception, "RSA decryption exception", "SecurityMgr::RSADecrypt()", msg);
}
return resultData;
}
RSA非对称加密可以这样使用吗
编辑:
在我们的应用程序中对连接字符串执行相同的操作(使用AES和RSA加密)(不涉及安装程序)效果良好。实际问题不是很清楚。但是,我在您的代码中看到了一些东西:
- 将密钥对(私有和公共)从提供程序导出到参数中。人们对布尔参数感到困惑。这并不意味着它只导出私钥。如果将其设置为true(导出私钥),则将导出公钥和私钥
- 与从RSA提供程序实例导出的密钥相同,您正在重新导入到同一提供程序中。这没有任何意义
- 删除ExportParameters和ImportParameters行,它们将一事无成。如果您在构造函数中指定的容器名称有效且存在,则您的密钥应该已经存在于RSA提供程序中
- 对于非对称加密,您使用私钥进行加密,因为您不共享私钥。然后使用公钥进行解密,因为另一方(接收方)应该只持有您的公钥才能进行解密。如果他们有你的私钥,整个方案就会被破坏
对于仍在阅读本文的任何人,从技术上讲,public>private(用public加密,用private解密)的过程称为加密,用于对能够解密的单个目标进行加密。反向过程(private>public)称为签名,它验证源的身份(因为只有他们可以“加密”它),但公钥(即任何人)可以“解密”(验证)它。这只是安全模型中语义上的一个重要区别。