37

我在 Azure 网站(不是托管服务)中有站点,我需要在那里处理带有私钥的 .pfx 证书。

var x509Certificate2 = new X509Certificate2(certificate, password);

但我面临以下异常:

System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
   at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

在文章http://blog.tylerdoerksen.com/2013/08/23/pfx-certificate-files-and-windows-azure-websites/我发现它发生是因为默认情况下系统使用用户的本地目录存储密钥。但是 Azure 网站没有本地用户配置文件目录。在同一篇文章中作者建议使用X509KeyStorageFlags.MachineKeySet标志。

var x509Certificate2 = new X509Certificate2(certificate, password, X509KeyStorageFlags.MachineKeySet);

但现在我有其他例外:

System.Security.Cryptography.CryptographicException: Access denied.

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
   at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

谁能帮我理解它为什么会发生以及如何解决它?

4

6 回答 6

98

我想您找到了解决方法,但是如果其他人为此苦苦挣扎,我在另一个 SO 问题中找到了答案:

如何从 PKCS#12 字节数组构造 X509Certificate2 抛出 CryptographicException(“系统找不到指定的文件。”)?

神奇的是指定 X509KeyStorageFlags 存储标志。例子:

var myCertificae = new X509Certificate2(
    certificateData,
    securePasswordString,
    X509KeyStorageFlags.MachineKeySet | 
    X509KeyStorageFlags.PersistKeySet | 
    X509KeyStorageFlags.Exportable);
于 2014-11-26T10:37:09.557 回答
6

Azure 网站现在具有将证书安装到证书存储的本机支持。你试过了吗?

此处的详细信息:http: //azure.microsoft.com/blog/2014/10/27/using-certificates-in-azure-websites-applications/

于 2014-12-02T00:13:04.447 回答
0

Azure 网站在共享环境中运行。我假设证书的构造函数试图在实例上创建一些临时信息并且它没有权限。

您可能必须升级到托管服务才能在提升的上下文中运行并执行此工作。

另外,您是否验证过密码正确?如果不需要密码,则至少必须将 string.Empty 传递给构造函数。传入 NULL 值也会导致此异常。

于 2013-09-27T14:42:36.567 回答
0

我遇到了完全相同的问题,并且为解决它而苦苦挣扎了好几个小时。在您提到的最后一个堆栈调用的文章中,函数是LoadCertFromFile,但在您(和我)的情况下,它是LoadCertFromBlob

所以我寻找 LoadCertFromBlob 并找到了这个:

为什么 X509Certificate2 有时无法从 blob 创建?

解决方案是进入 IIS 并将应用程序池标识从“ApplicationPoolIdentity”更改为“LocalService”,以便将证书加载到正确的本地文件夹中。

于 2013-10-11T07:31:40.907 回答
0

在 Azure 网站/Web 应用程序/移动应用程序中 - 您必须使用应用服务计划来导入 SSL 证书 - 所以它不应该是免费或共享的。您不仅可以导入 SSL 证书,还可以导入示例代码签名证书,并在 signtool 或 PowerShell 中使用它。

我在https://vmplace.eu/中使用了这种方法

如果您尝试使用免费或共享计划,您会收到错误 - 因此在这些计划中的 Azure 中存在其他版本的 .NET 框架。

你也可以参考这个项目:https ://github.com/onovotny/SignService

mvpbuzz

于 2017-05-02T11:57:52.373 回答
0

我按照官方文档中的说明解决了这个问题。不确定这是否是以前的选项,但现在是,并且易于使用/实施。

  1. 首先,我将 .pfx 证书上传到我的 Azure 应用服务,并在要求输入密码时输入了密码。复制了指纹。

  2. 然后我从 Azure 控制台中运行以下命令(我只添加了一个指纹)。这很重要,因为它使您的应用能够访问证书:

az webapp config appsettings set --name <app-name> --resource-group <resource-group-name> --settings WEBSITE_LOAD_CERTIFICATES=<comma-separated-certificate-thumbprints>
  1. 我使用以下方法将之前上传的 .pfx 证书加载到我的应用程序中:
public X509Certificate2 GetAzureCertificate(string thumbprint, bool validOnly)
{
    using (var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
    {
        certStore.Open(OpenFlags.ReadOnly);

        var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, validOnly);
        var cert = certCollection.OfType<X509Certificate2>().FirstOrDefault();

        if (cert == null)
        {
            throw new Exception($"Cert not found. Total cert count : {certStore.Certificates.Count}.");
        }

        return cert;
    }
}
于 2020-06-09T09:27:58.037 回答