一位用户最近在使用我的软件时报告了一个奇怪的错误。我使用 DSA 签名来验证许可证。当软件导入公钥以验证签名时,DSA 提供程序的FromXmlString方法会引发CryptographicException,其描述为“密钥在指定状态下无效。 ”
从 System.Security.Cryptography.Utils.CreateProvHandle 调用的 _OpenCSP 方法似乎返回 NTE_BAD_KEY_STATE (0x8009000b)。这是第一次有人向我报告此错误,并且该代码已多年未更改。
造成这种情况的可能原因是什么?屏蔽权限错误?损坏的 CAPI 安装?被.net 信任/权限设置阻止?由密钥存储提供程序存储的垃圾,还是 KSP 向 cryptoapi 返回意外的东西?
我已经用谷歌搜索了错误代码/描述/等,但没有找到任何可能导致这种情况的真正答案......
失败的代码的隔离版本在这里:http: //forum.huagati.com/getattachment.ashx?fileid=78
using System;
using System.Security.Cryptography;
using System.Reflection;
public class Test
{
public static void Main()
{
try
{
string key = "<DSAKeyValue><P>wrjxUnfKvH/1s5cbZ48vuhTjflRT5PjOFnr9GeUPZSIoZhYATYtME4JRKrXBtSkyioRNtE1xgghbGAyvAJ5jOWw88fLBF+P1ilsZyq72G1YcbB+co8ImQhAbWKmdCicO9/66Th2MB+7kms/oY3NaCzKEuR7J3b23dGrFpp4ccMM=</P><Q>xmxoSErIJCth91A3dSMjC6yQCu8=</Q><G>bwOLeEaoJHwSiC3i3qk9symlG/9kfzcgrkhRSWHqWhyPAfzqdV1KxJboMpeRoMoFr2+RqqKHgcdbzOypmTeN4QI/qh4nSsl5iEfVerarBOrFuRdOVcJO0d8WE233XQznd1K66nXa5L8d9SNZrM6umZ1YuBjhVsTFdPlIXKfGYhk=</G><Y>wZnEEdMUsF3U3NBQ8ebWHPOp37QRfiBn+7h5runN3YDee1e9bC7JbJf+Uq0eQmU8zDs+avEgD68NpxTKEHGr4nQ3rW6qqacj5SDbwO7nI6eN3wWrVhvrWcQm0tUO93m64HsEJREohfoL+LjqgrqIjZVT4D1KXE+k/iAb6WKAsIA=</Y><J>+zmcCCNm2kn1EXH9T45UcownEe7JH+gl3Lw2lhVzXuX/dYp5sGCA2lK119iQ+m3ogjOuwABATCVFLo6J66DsSlMd0I8WSD5WKPvypQ7QjY0Iv71J2N0FW0ZXpMlk/CE8zq4Z7arM1N564mNe</J><Seed>QDrZrUFowquY5Uay8YtUFOXnv28=</Seed><PgenCounter>Gg==</PgenCounter></DSAKeyValue>";
DSACryptoServiceProvider csp2 = new DSACryptoServiceProvider();
csp2.FromXmlString(key);
Console.WriteLine("Success!");
}
catch (Exception ex)
{
int hResult = 0;
try
{
PropertyInfo pi = typeof(Exception).GetProperty("HResult", BindingFlags.NonPublic | BindingFlags.Instance);
hResult = (int)pi.GetValue(ex, null);
}
catch (Exception ex2)
{
Console.WriteLine("HResult lookup failed: " + ex2.ToString());
}
Console.WriteLine("Initializing CSP failed: " + ex.ToString() + "\r\nHResult: " + hResult.ToString("x"));
}
Console.WriteLine("\r\nPress Enter to continue");
Console.ReadLine();
}
}
...并在受影响用户的机器上返回:
Initializing CSP failed: System.Security.Cryptography.CryptographicException: Ke
y not valid for use in specified state.
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters paramete
rs, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.get_StaticDssProvHandle()
at System.Security.Cryptography.DSACryptoServiceProvider.ImportParameters(DSA
Parameters parameters)
at System.Security.Cryptography.DSA.FromXmlString(String xmlString)
at Test.Main()
HResult: 8009000b
更新:在同一台机器上的 .net fx 2.0 下运行时,相同的代码工作正常,但在 .net fx 4.0 下失败。
更新 2: DSA 提供程序似乎会查找存储在 %APPDATA%\Microsoft\Crypto\DSS\[SID] 下的密钥,即使使用现有密钥进行初始化也是如此。会不会和这个机制有冲突?任何人都知道更多关于密钥存储是如何运作的,以及为什么从字符串加载公钥时它会被命中?