79

我正在尝试使用自签名证书(c#):

X509Certificate2 cert = new X509Certificate2(
    Server.MapPath("~/App_Data/myhost.pfx"), "pass");

在共享网络托管服务器上,我收到一个错误:

System.Security.Cryptography.CryptographicException: An internal error occurred.

堆栈跟踪以

System.Security.Cryptography.CryptographicException.
    ThrowCryptogaphicException(Int32 hr) +33
System.Security.Cryptography.X509Certificates.X509Utils.
    _LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, 
        Boolean persistKeySet, SafeCertContextHandle& pCertCtx) +0
System.Security.Cryptography.X509Certificates.X509Certificate.
    LoadCertificateFromFile(String fileName, Object password, 
        X509KeyStorageFlags keyStorageFlags) +237
System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(
    String fileName, String password) +131

在我的开发机器上,它加载正常。我加载 *.pfx 而不是 *.cer 文件的原因是因为我需要访问私钥(cer 文件加载正常)。我像这样在我的开发机器上制作了 pfx:

makecert -r -n "CN=myhost.com, E=admin@myhost.com" -sky exchange -b 01/01/2009
    -pe -sv myhost.pvk myhost.cer
<b>pvk2pfx</b> -pvk myhost.pvk -spc myhost.cer -pfx myhost.pfx -po pass</code>

我正在使用 v5.131.3790.0 版本的 makecert

4

2 回答 2

146

使用本地计算机存储获取私钥:

X509Certificate2 cert = new X509Certificate2("myhost.pfx", "pass",
    X509KeyStorageFlags.MachineKeySet);

MachineKeySet被描述为“私钥存储在本地计算机存储中,而不是当前用户存储中”。没有标志的默认设置是放置在用户存储中。

即使您从磁盘读取证书并将其存储在对象中,私钥仍存储在 Microsoft Cryptographic API Cryptographic Service Provider 密钥数据库中。在托管服务器上,ASP.NET 进程没有访问用户存储的权限。

另一种方法(根据下面的一些评论)是修改 IIS 配置或应用程序池标识——它们确实有效。但是,这假设可以访问这些配置项,但情况可能并非如此(例如,在共享主机环境中)。

于 2009-08-28T06:48:09.467 回答
13

我尝试了 Randy 将其更改为 MachineKeySet 的解决方案,但随后收到错误消息:

“密钥在指定状态下无效”

因此,经过一番谷歌搜索后,我发现了一篇建议将其更改为的帖子:

var certificate = new X509Certificate2(certKeyFilePath, passCode, 
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet |       
X509KeyStorageFlags.PersistKeySet );

这解决了我的问题。

我还没有尝试在 IIS 配置中更改设置应用程序池设置的建议。为此,请转到您网站应用程序池的高级设置,然后将“加载用户配置文件”设置为 true。当此设置为 false 时,显然无法访问密钥容器。

于 2015-09-09T09:17:57.143 回答