Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对于一个用户,从xml字符串导入DSA密钥失败。权限?坏的安装?坏的KSP?_C#_.net_Cryptography_Cryptoapi_Dsa - Fatal编程技术网

C# 对于一个用户,从xml字符串导入DSA密钥失败。权限?坏的安装?坏的KSP?

C# 对于一个用户,从xml字符串导入DSA密钥失败。权限?坏的安装?坏的KSP?,c#,.net,cryptography,cryptoapi,dsa,C#,.net,Cryptography,Cryptoapi,Dsa,一个用户最近报告说,在使用我的软件时出现了一个奇怪的错误。我使用DSA签名来验证许可证。当软件导入公钥以验证签名时,DSA提供程序的方法会抛出一个加密异常,描述为“密钥在指定状态下无法使用” 似乎从System.Security.Cryptography.Utils.CreateProvHandle调用的_OpenCSP方法返回NTE_BAD_KEY_状态(0x8009000b)。这是第一次有人向我报告这个错误,而且代码已经多年没有更改了 可能的原因是什么?屏蔽权限错误?损坏的CAPI装置?是否

一个用户最近报告说,在使用我的软件时出现了一个奇怪的错误。我使用DSA签名来验证许可证。当软件导入公钥以验证签名时,DSA提供程序的方法会抛出一个加密异常,描述为“密钥在指定状态下无法使用”

似乎从System.Security.Cryptography.Utils.CreateProvHandle调用的_OpenCSP方法返回NTE_BAD_KEY_状态(0x8009000b)。这是第一次有人向我报告这个错误,而且代码已经多年没有更改了

可能的原因是什么?屏蔽权限错误?损坏的CAPI装置?是否被.net信任/权限设置阻止?密钥存储提供程序存储的垃圾,或返回cryptoapi意外内容的KSP

我已经在谷歌上搜索了错误代码/描述/等等,但没有找到任何真正的答案来解释是什么导致了这一情况

失败代码的独立版本如下所示:

更新:在同一台计算机上运行.net fx 2.0时,相同的代码工作正常,但在.net fx 4.0下失败


更新2:DSA提供程序似乎会查找存储在%APPDATA%\Microsoft\Crypto\DSS\[SID]下的密钥,即使在使用现有密钥初始化时也是如此。这一机制是否存在冲突?任何人都知道密钥存储是如何工作的,以及从字符串加载公钥时为什么会被击中?

您描述的问题似乎很有趣,但如果没有一些额外的信息和一些实验,很难确定原因是什么。所以我试着描述一下我是如何理解这个问题的

首先.NET加密类在内部使用非托管CryptoAPI。因此方法
\u OpenCSP
在内部调用函数。在其文档中,我们可以阅读以下有关错误的信息
NTE\u BAD\u KEY\u STATE
(0x8009000BL):

用户密码已自更改 私钥被加密了

DSA提供程序使用的用户私钥保存为目录
%APPDATA%\Microsoft\Crypto\DSS\[SID]
中的文件,并将使用相对复杂的算法进行加密,您可以从中读取。重要的是要了解目录中的文件对应于用户密钥的密钥容器。通常,用户可以完全访问文件系统中的文件。文件将使用依赖于用户密码的密钥进行加密。在许多标准情况下,文件在密码更改后将重新加密,但恢复算法取决于许多因素。如果密码被重置而不是由用户自己更改(由域管理员/帐户操作员等进行),则目录
%APPDATA%\Microsoft\Crypto\DSS\[SID]
的旧包含可能不会更有用。例如,如果用户不是Active Directory用户(本地用户),并且本地管理员重置了其密码,则会出现加密容器问题

因此,第一个建议是询问用户是否重置了其Active Directory密码。接下来,您应该验证用户配置文件中是否存在目录
%APPDATA%\Microsoft\Crypto\DSS\[SID]
,并且用户对文件系统中的目录具有完全访问权限。您应该从目录中删除所有文件(以前创建文件的备份副本)。顺便说一句,了解用户是否有中央保存的配置文件(保存在服务器上)很有趣。如果它具有中心配置文件,则可以验证用户的另一台计算机上是否存在您描述的相同问题,并且其他用户在其原始计算机上不会有问题

我不太清楚的另一个问题是为什么使用目录
%APPDATA%\Microsoft\Crypto\DSS\[SID]
中的密钥容器,因为您只使用公钥。在CryptoAPI中,应使用
CryptAcquireContext
NULL
作为
pszContainer
参数,并在
dwFlags
中使用
CRYPT\u VERIFYCONTEXT
。我不确定.NET是否使用了
CRYPT\u VERIFYCONTEXT
标志,这可能会间接导致您的问题

您可以使用参数创建
DSACryptoServiceProvider
。另一侧的属性在.NET 4.0中使用值进行扩展。
csproviderflags.CreateEphemeralKey
的描述与
CryptAcquireContext
函数的
CRYPT\u VERIFYCONTEXT
标志的描述非常接近。所以use可以尝试使用或
csproviderflags.CreateEphemeralKey
csproviderflags.UseDefaultKeyContainer
NULL
as
pszContainer
的参数
CryptAcquireContext
也表示默认密钥容器)

此外,如果可能的话,您可以尝试在可以重现问题的计算机上调试问题。要进行调试,您可以使用.NET源代码,这些源代码可以从中启用(请参阅和)或下载。然后,您可以回答有关当前程序中使用的
CspParameters
值的一些问题,并比较.NET 3.5和.NET 4.0的值

如果我所写的内容无助于解决问题,请您在问题后面附加其他信息:

  • 哪种操作系统和哪种service pack具有可以重现问题的计算机
  • 问题是否取决于用户?我的意思是:同一台计算机上的其他用户也有同样的问题吗
  • 域(active directory)用户或本地用户帐户是否存在问题?有问题的用户是否有保存在服务器上的中央用户配置文件?如果他有,那么p
    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
    
    static string GenerateDsaKeyInDefaultContainer()
    {
        const int PROV_DSS_DH = 13;
        CspParameters cspParam = new CspParameters(PROV_DSS_DH);
        cspParam.KeyContainerName = null;
        cspParam.KeyNumber = (int)KeyNumber.Signature;
        cspParam.Flags = CspProviderFlags.UseDefaultKeyContainer;
        DSACryptoServiceProvider csp = new DSACryptoServiceProvider(cspParam);
        return csp.CspKeyContainerInfo.UniqueKeyContainerName;
    }