2009-02-17 46 views
9

我有一个ASP.NET Web服务,它接收一个字节数组,代表包含X.509证书的.pfx文件的内容。服务器端代码使用的是System.Security.Cryptography.X509Certificate2构造函数加载从字节证书:为什么X509Certificate2有时无法从blob创建?

X509Certificate2 native_cert = new X509Certificate2(
       pkcs12_buf /*byte array*/, 
       password, 
       X509KeyStorageFlags.PersistKeySet | 
       X509KeyStorageFlags.Exportable 
      ); 

取决于谁是我的服务进程正在运行的,这个调用要么成功,或失败并产生“内部错误”异常。异常堆栈上的最后一个调用为X509Utils._LoadCertFromBlob,这是mscore.dll中的非托管代码。

使用服务帐户凭证在交互式登录中从控制台应用程序运行时,此代码成功。在使用服务帐户凭证的应用程序池中运行w3wp.exe时失败。将应用程序池标识更改为管理员可以修复问题,因此它必定是一个特权问题,但我不知道此特权可能需要什么权限。代码不会触及文件系统或Windows证书存储区。

[更新:更多信息]
此错误出现在Windows事件日志:

*Cryptographic Parameters:* 
**Provider Name:** Microsoft Software Key Storage Provider 
**Algorithm Name:** Not Available. 
**Key Name:** {E182E13B-166D-472A-A24A-CBEF0808E9ED} 
    **Key Type:** User key. 

*Cryptographic Operation:* 
**Operation:** Open Key. 
    **Return Code:** 0x2 

任何想法?

回答

8

我只是找到了解决这一个自己:

X509KeyStorageFlags flags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet; 

X509Certificate2 cert = new X509Certificate2(pkcs12_buf, password, flags); 

诀窍这里将使用本地密钥存储区MachineKeySet标志而不是用户配置文件密钥存储区,如果您未指定其他位置,则该默认值为默认值。由于ASP.NET进程标识不会加载用户配置文件存储,因此在以编程方式导入证书时无法访问存储,但可以访问机器存储。

我认为PersistKeySet只是保持私钥加载,但我不确定它到底做了什么 - 如果您因为某些原因需要访问私钥,这是必需的。

2

尝试授予ASP.NET帐户权限到以下文件夹:C:\Documents And Settings\All Users\Microsoft\Crypto\RSA\MachineKeys\(可根据您的环境会发生变化)

+0

我认为你在正确的轨道上,但似乎并没有试图访问文件系统。成功的帐户在用户的个人配置文件(而不是AllUsers)下访问Microsoft \ Crypto \ RSA。根据procmon的说法,失败的人甚至不会尝试访问文件系统。 – jlew 2009-02-17 23:30:23

+0

此权限更改适用于Win2k8上的我。为我节省了大量的时间调试。谢谢! – CodingWithSpike 2011-06-25 02:54:30

相关问题