Azure网站中的站点无法处理X509Certificate2证书

37

我在Azure Websites(非托管服务)上有一个网站,我需要在那里处理带有私钥的.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)

有人能帮我理解为什么会发生这种情况以及如何修复它吗?

6个回答

98

我猜你已经找到了解决方法,但如果其他人也遇到了类似的问题,我在另一个SO问题中找到了答案:

如何从PKCS#12字节数组构造X509Certificate2会抛出CryptographicException("The system cannot find the file specified.")?

关键是指定X509KeyStorageFlags存储标志。例如:

var myCertificae = new X509Certificate2(
    certificateData,
    securePasswordString,
    X509KeyStorageFlags.MachineKeySet | 
    X509KeyStorageFlags.PersistKeySet | 
    X509KeyStorageFlags.Exportable);

1
谢谢。这也帮助了我在WebJob实例中解决问题。之前我一直收到错误信息:作业由于退出代码-1073740940而失败。 - Thomas Edmondson
这是唯一的搜索结果,显示错误号1073740940。当我将其作为WebJob运行时,没有附加错误,只有退出代码。非常感谢@ThomasEdmondson,这让我很疯狂。 - Yodacheese
1
这应该是答案。 - Maxim Balaganskiy
这在几个月前对我起作用 - 但自从我今天启动了一个新的Azure网站以来,我一直收到相同的错误,尽管我正在指定所有三个X509KeyStorageFlags值。我想知道Azure的配置是否有变化。 - Dai
4
顺便提一句:您可以将securePasswordString设置为null。我从Azure KeyVault中获取了完整的PPK证书,得到的是一个cer=byte[],但没有密码。这对我起作用了。 - Herb Stahl
显示剩余7条评论

6

1
那个链接救了我的一天。非常感谢! - Luiso
运行得非常顺畅。 - S.A.
旧门户网站中管理网站的部分已被弃用。 - Nix

1

我通过遵循官方文档中的说明解决了这个问题。不确定以前是否有这个选项,但现在有了,并且很容易使用/实现。

  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>

我使用了以下方法将之前上传的.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;
    }
}

0
在 Azure 网站 / Web 应用程序 / 移动应用中,您必须使用 App Service 计划,以便导入 SSL 证书 - 因此不应该是免费或共享的。您不仅可以导入 SSL 证书,还可以导入例如代码签名证书,并在 signtool 或 PowerShell 中使用它。
我在https://vmplace.eu/中使用了这种方法。
如果您尝试使用免费或共享计划,则会收到错误消息 - 因此,在 Azure 中这些计划中有其他版本的 .NET Framework。
您还可以参考此项目:https://github.com/onovotny/SignService

mvpbuzz


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

您可能需要升级到托管服务以便在提升的上下文中运行并执行此工作。

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

我们寻找解决方案没有成功,所以我们将应用程序迁移到了托管服务。 - Roman Oleynik

0

我曾经遇到过完全相同的问题,为了解决它我苦苦挣扎了数小时。

在你提到的文章中,最后一个堆栈调用是函数LoadCertFromFile,但在你(和我)的情况下,它是LoadCertFromBlob

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

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

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


不,我不从 blobs 中加载证书,我是从字节数组中加载的。 是的,你说得对,问题出在应用程序池标识的访问权限上。但我将我的应用程序部署在Azure网站上。我无法更改IIS的应用程序池标识。因此,我将其移动到托管服务中。 - Roman Oleynik
我是在谈论你所报告的异常中的“_LoadCertFromBlob”调用。 - Sean
或者你可以坚持使用应用程序身份,但将Load User Profile改为true。 - deerchao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接