“发生了内部错误。” 使用X509Certificate2加载pfx文件时


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>

我正在使用makecert v5.131.3790.0版本


也许这篇文章可以对您有所帮助:codeproject.com/KB/WCF/wcfcertificates.aspx
Emmanuel

我收到错误消息the system cannot find the file specified。@Randy Levy的回答对我有用!
杰西

Answers:


145

将本地计算机存储区用作私钥:

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

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

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

另一种方法(按照下面的一些评论)是修改IIS配置或应用程序池标识-可以起作用。但是,这假定可以访问这些配置项,而事实并非如此(例如,在共享主机环境中)。


3
是的,它有帮助,谢谢。你能解释为什么吗?文档说没有什么帮助。

2
你救了我的日子。奇怪的是,在将解决方案升级到.NET 4.0之前,它已经在我的机器上工作了
Marc Climent 2010年

1
确实,所有需要做的就是设置X509KeyStorageFlags.MachineKeySet参数。引发该异常仅声明“发生内部错误”真是可悲。不是很有帮助。
Nicholi 2011年

2
您还可以将私钥上的更多特权添加到分配给应用程序池的帐户。或将应用程序池标识更改为“本地服务”。
guzart 2011年

1
而对于更快解决问题/解决方法检查:stackoverflow.com/questions/9951729/...
西普里安Teiosanu

13

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

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

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

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

这解决了我的问题。

我尚未尝试过更改IIS配置中的设置应用程序池设置的建议。为此,请转到网站应用程序池的“高级设置”,然后将“加载用户个人资料”设置为true。如果此设置为false,则显然无法访问密钥容器。


我遇到了上述错误,您的解决方案已帮助解决了该错误。谢谢。
dotcoder

我不喜欢没有帮助的评论(像这样的评论),但让我告诉您,您可以节省我的时间。谢谢!
rasputino'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.