c# - C#:使用计划的 Azure Functions 中不存在密钥集
问题描述
我们中的许多人在尝试使用 X509Certificate2 时都遇到了“Keyset does not esist”异常。症状是:
您将 .pfx 加载到 X509Certificate2
您在任何需要私钥的操作中使用它
你得到“键集不存在”异常。
在代码中,它如下所示:
string CreateJWTToken(byte[] certificate, string psw, string serviceUserIss, string serviceUserSub, string serviceUserAud)
{
using (X509Certificate2 combinedCertificate = new X509Certificate2(certificate, psw,
X509KeyStorageFlags.MachineKeySet
| X509KeyStorageFlags.PersistKeySet
| X509KeyStorageFlags.Exportable))
{
var signingKey = new X509SecurityKey(combinedCertificate);
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);
var header = new JwtHeader(credentials);
var payload = new JwtPayload
{
{ "iss", serviceUserIss},
{ "sub", serviceUserSub},
{ "aud", serviceUserAud},
{ "exp", $"{unixTimestamp}"}
};
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(secToken); // here exception is thrown
}
}
它在本地运行良好,甚至在本地 Azure Functions 主机中也能正常工作,但由于某种原因,它有时(例如在 5% 的情况下)在 Azure Function(定时器触发)中运行时会抛出“密钥集不存在”的消费计划。
解决方案
问题似乎在于 Azure Functions 消费计划如何与证书一起使用的一些细微差别。
我不知道细节,但X509Certificate2
有时会清除 ' 的 PrivateKey ......通过某事。它是积极的垃圾收集器吗?它与自动缩放有关,还是与不同主机之间共享的资源有关?我不知道。
但问题似乎通过避免使用 X509Certificate2 来解决,通过使用 BouncyCastle 的机制从 PFX 加载私钥。请参阅下面的代码片段。
下面的代码段也使用 Jose.JWT 来创建 JWT 令牌。
private static string CreateJWTTokenBountyCastle(byte[] certificate, string psw, string serviceUserIss, string serviceUserSub, string serviceUserAud)
{
string jwt;
using (RSACryptoServiceProvider rsax = OpenCertificate(certificate, psw)) // open using BouncyCastle and avoid usage of X502Certificate2
{
Dictionary<string, object> payload = new Dictionary<string, object>(){
{ "iss", serviceUserIss },
{ "sub", serviceUserSub},
{ "aud", serviceUserAud},
jwt = Jose.JWT.Encode(payload, rsax, Jose.JwsAlgorithm.RS256);
}
return jwt;
}
private static RSACryptoServiceProvider OpenCertificate(byte[] certB, string pwd)
{
MemoryStream ms = new MemoryStream(certB);
Pkcs12Store st = new Pkcs12Store(ms, pwd.ToCharArray());
var alias = st.Aliases.Cast<string>().FirstOrDefault(p => st.IsKeyEntry(p));
AsymmetricKeyEntry keyEntry = st.GetKey(alias);
var kkey = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyEntry.Key);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(kkey);
return rsa;
}
推荐阅读
- google-sheets - 如何在 Google 表格中添加月份并获取当年的月份
- mongodb - 用于获取和删除 2018 年记录的 Mongo db 查询
- c++ - 为什么“不调试就启动”后什么都没有出来?它显示“filenook.exe 已触发断点”。“开始调试”之后
- c++ - 将运行时值映射到模板类型递归太远
- python - 在python中将文本转换为数据框
- angular - Angular 9 Reactive forms显示基于单选按钮选择的隐藏div
- g1ant - 在 G1ANT Studio 中找不到插件的命令
- excel - Range.Select 循环一次后出错
- php - 使用 ajax 调用加载视图 codeigniter
- python - Maya - 查询动画曲线数据