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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1345262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:25:17  来源:igfitidea点击:

"An internal error occurred." when loading pfx file with X509Certificate2

c#x509certificatepfx

提问by

I'm trying use self-signed certificate (c#):

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

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

on a shared web hosting server and I got an error:

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

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

stack trace ends with

堆栈跟踪以

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

On my dev machine it loads ok. The reason I load *.pfx not a *.cer file because I need a private key access (cer file loads Ok). I made pfx on my dev mochine like that:

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

makecert -r -n "CN=myhost.com, [email protected]" -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>

I am using version v5.131.3790.0 of makecert

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

采纳答案by Randy supports Monica

Use the local computer store for the private key:

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

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

MachineKeySetis described as "private keys are stored in the local computer store rather than the current user store". The default with no flags is to place in the user store.

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

Even though you are reading the certificate from disk and storing it in an object the private keys are still stored in the Microsoft Cryptographic API Cryptographic Service Provider key database. On the hosting server the ASP.NET process does not have permission to access the user store.

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

Another approach (as per some comments below) is to modify the IIS Configuration or App Pool identity -- which do work. However, this assumes that there is access to these configuration items which may not be the case (e.g. in a shared hosting environment).

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

回答by Myke Black

I tried Randy's solution of changing it to MachineKeySet, but then got the error message:

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

"key not valid for use in specified state"

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

So after a little googling around I found a post that suggested changing it to:

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

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

and this sorted out my issues.

这解决了我的问题。

I haven't yet tried the suggestion to change the setting app pool setting in the IIS configuration. To do this go to the Advanced Settings for your site's app pool then set "load user profile" to true. When this setting is false, the key containers aren't accessible apparently.

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