问题描述
我有一个 .NET Framework 4.7 应用程序,它允许用户上传 PFX 或 PKCS#12 格式的 X.509 证书(想想:包含私钥的SSL 证书"),然后将证书加载到 System.Security.Cryptography.X509Certificates.X509Certificate2
实例.由于我的应用程序代码还需要重新导出证书,因此我指定了 X509KeyStorageFlags.Exportable
选项.
I have a .NET Framework 4.7 application that allows users to upload X.509 certificates in PFX or PKCS#12 format (think: "SSL certificates" with the private key included), it then loads the certificate into a System.Security.Cryptography.X509Certificates.X509Certificate2
instance. As my application code also needs to re-export the certificate I specify the X509KeyStorageFlags.Exportable
option.
在我的生产网络服务器上的 IIS 下运行时,未加载 w3wp.exe
在其下运行的身份的 Windows 用户配置文件,因此我没有指定 UserKeySet
标志.
When running under IIS on my production web-server, the Windows user-profile for the identity that w3wp.exe
runs under is not loaded, so I do not specify the UserKeySet
flag.
String filePassword = ...
Byte[] userProvidedCertificateFile = ...
using( X509Certificate2 cert = new X509Certificate2( rawData: userProvidedCertificateFile, password: filePassword, keyStorageFlags: X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet )
{
...
}
在 2017 年初,我将此代码部署到 Azure 应用服务(又名 Azure 网站)实例,它运行良好 - 在最初失败后,因为我确实设置了 UserKeySet
标志(就像 Azure 应用服务一样不加载用户配置文件证书存储.
In early 2017 I deployed this code to an Azure App Service (aka Azure Website) instance and it worked okay - after initially failing because I did have the UserKeySet
flag set (as Azure App Services do not load a user-profile certificate store.
但是,自 2017 年年中(可能在 5 月或 6 月左右)以来,我的应用程序已经停止工作 - 我假设 Azure 应用程序服务已移至更新的系统(尽管 Kudu 报告我的应用程序正在 Windows Server 2012 上运行(NT 6.2.9200.0
).
However, since mid-2017 (possibly around May or June) my application has stopped working - I assume the Azure App Service was moved to an updated system (though Kudu reports my application is running on Windows Server 2012 (NT 6.2.9200.0
).
目前失败,并显示两条因输入而异的错误消息:
It currently fails with two error messages that varied depending on input:
CryptographicException
"系统找不到指定的文件."CryptographicException
访问被拒绝."
CryptographicException
"The system cannot find the file specified."CryptographicException
"Access denied."
我编写了一个广泛的测试用例,它尝试了 X509Certificate2
构造函数参数的不同组合,以及有无 WEBSITE_LOAD_CERTIFICATES
Azure 应用程序设置.
I wrote an extensive test-case that tries different combinations of X509Certificate2
constructor arguments, as well as with and without the WEBSITE_LOAD_CERTIFICATES
Azure application setting.
以下是我在处理上传的 PFX/PKCS#12 证书文件时的发现:该文件包含私钥且没有密码保护:
Here are my findings when working with an uploaded PFX/PKCS#12 certificate file that contains a private key and does not have password-protection:
- 在我的开发箱上运行在 IIS Express 下:
- 无论
X509KeyStorageFlags
值如何,加载证书文件始终成功. - 导出证书文件至少需要
X509KeyStorageFlags.Exportable
.
- Running under IIS Express on my development box:
- Loading the certificate file always succeeds, regardless of
X509KeyStorageFlags
value. - Exporting the certificate file requires at least
X509KeyStorageFlags.Exportable
.
- 加载证书文件需要
X509KeyStorageFlags.UserKeySet
未设置,否则总是成功. - 导出证书文件至少需要
X509KeyStorageFlags.Exportable
,否则总是成功,否则失败并显示Key not valid for use in specified state".
- Loading the certificate file requires that
X509KeyStorageFlags.UserKeySet
is not set, but otherwise always succeeds. - Exporting the certificate file requires at least
X509KeyStorageFlags.Exportable
, but otherwise always succeeds, otherwise it fails with "Key not valid for use in specified state."
- 加载设置了
MachineKeySet
且UserKeySet
设置为 not 的证书失败,并出现CryptographicException
:访问被拒绝." - 使用任何其他
keyStorageFlags
值加载证书,包括UserKeySet |机键集 |可导出
或仅DefaultKeySet
失败并出现CryptographicException
:系统找不到指定的文件." - 由于我根本无法加载证书,因此无法测试导出证书.
- Loading the certificate with
MachineKeySet
set andUserKeySet
is not set fails with aCryptographicException
: "Access denied." - Loading the certificate with any other
keyStorageFlags
value, including values likeUserKeySet | MachineKeySet | Exportable
or justDefaultKeySet
fails with aCryptographicException
: "The system cannot find the file specified." - As I was not able to load the certificate at all I could not test exporting certificates.
- 使用
MachineKeySet
和UserKeySet
加载证书 未 设置,失败并出现CryptographicException代码>:访问被拒绝.".
- 像
UserKeySet
和UserKeySet 这样的值 |MachineKeySet
和Exportable
将起作用.
- Loading the certificate with
MachineKeySet
andUserKeySet
is not set, fails withCryptographicException
: "Access denied." .- So values like
UserKeySet
andUserKeySet | MachineKeySet
andExportable
will work.
因此,
WEBSITE_LOAD_CERTIFICATES
似乎可以工作 - 但前提是加载到X509Certificate2
实例中的证书具有与WEBSITE_LOAD_CERTIFICATES
中指定的指纹相同的指纹代码>.So it seems that
WEBSITE_LOAD_CERTIFICATES
seems to work - but only if the certificate being loaded into anX509Certificate2
instance has the same thumbprint as specified inWEBSITE_LOAD_CERTIFICATES
.有没有办法解决这个问题?
Is there any way around this?
推荐答案
我想了更多关于
WEBSITE_LOAD_CERTIFICATES
似乎有所作为 - 但我有一种有趣的感觉 真的 仅使用指定的证书指纹.I thought more about how
WEBSITE_LOAD_CERTIFICATES
seems to make a difference - but I had a funny feeling about it really only working with the certificate thumbprint that's specified.所以我将
WEBSITE_LOAD_CERTIFICATES
值更改为虚拟指纹 - 任意 40 个字符的 Base16 字符串,然后重新运行我的测试 - 即使指纹与证书无关,它也能正常工作我正在合作.So I changed the
WEBSITE_LOAD_CERTIFICATES
value to a dummy thumbprint - an arbitrary 40-character Base16 string, and re-ran my test - and it worked, even though the thumbprint had no relation to the certificate I was working with.似乎只需定义
WEBSITE_LOAD_CERTIFICATES
即可使 Azure 网站能够使用X509Certificate
和X509Certificate2
- 即使加载的证书是从未安装到任何系统范围或用户配置文件的证书存储中,甚至从未从中检索过(如 MMC.exe 的证书管理单元中所示).It seems that simply having
WEBSITE_LOAD_CERTIFICATES
defined will enable the the Azure website's ability to useX509Certificate
andX509Certificate2
- even if the loaded certificate is never installed into, or even retrieved from, any systemwide or user-profile certificate store (as seen in the Certificates snap-in for MMC.exe).这种行为似乎没有记录在任何地方,所以我在这里提到它.
This behaviour does not seem to be documented anywhere, so I'm mentioning it here.
我已就此联系 Azure 支持.
I've contacted Azure support about this.
关于我在年中注意到的行为变化 - 我很可能确实为我们正在使用的测试证书设置了
WEBSITE_LOAD_CERTIFICATES
.当我在今年晚些时候在 6 月左右进行新部署时,我必须重置 应用程序设置,该设置删除了WEBSITE_LOAD_CERTIFICATES
并因此破坏了X509Certificate2
实例.Regarding the behavioural change I noticed at mid-year - it's very likely that I did have
WEBSITE_LOAD_CERTIFICATES
originally set for a testing certificate we were using. When I made a new deployment later in the year around June I must have reset the Application settings which removed theWEBSITE_LOAD_CERTIFICATES
and so brokeX509Certificate2
instances.- 在
portal.azure.com
中打开您的 Azure 应用服务(Azure 网站)刀片 - 转到应用设置页面
- 滚动到应用设置
- 添加一个新的条目键:
WEBSITE_LOAD_CERTIFICATES
,并为其提供一个虚拟(伪造的、虚构的、随机生成的)值. X509Certificate2(Byte[], String, X509KeyStorageFlags)
构造函数现在可以工作,但请注意:keyStorageFlags: X509KeyStorageFlags.MachineKeySet
将失败并显示访问被拒绝"- 所有其他
keyStorageFlags
值,包括MachineKeySet |UserKeySet
会成功(即MachineKeySet
本身会失败,但MachineKeySet
与其他位设置一起使用会起作用.
- Open your Azure App Service (Azure Website) blade in
portal.azure.com
- Go to the Application settings page
- Scroll to App settings
- Add a new entry key:
WEBSITE_LOAD_CERTIFICATES
, and provide a dummy (fake, made-up, randomly-generated) value for it. - The
X509Certificate2( Byte[], String, X509KeyStorageFlags )
constructor will now work, but note:keyStorageFlags: X509KeyStorageFlags.MachineKeySet
will fail with "Access denied"- All other
keyStorageFlags
values, includingMachineKeySet | UserKeySet
will succeed (i.e.MachineKeySet
by itself will fail, butMachineKeySet
used in conjunction with other bits set will work).
这篇关于自 2017 年中以来 Azure 应用服务(Azure 网站)上的 X509Certificate2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- So values like
- 像
- Loading the certificate file always succeeds, regardless of
- 无论