我有一个WebJob需要创建一个JWT令牌来与外部服务进行通信。当我在本地计算机上运行WebJob时,以下代码有效:
public static string SignES256(byte[] p8Certificate, object header, object payload)
{
var headerString = JsonConvert.SerializeObject(header);
var payloadString = JsonConvert.SerializeObject(payload);
CngKey key = CngKey.Import(p8Certificate, CngKeyBlobFormat.Pkcs8PrivateBlob);
using (ECDsaCng dsa = new ECDsaCng(key))
{
dsa.HashAlgorithm = CngAlgorithm.Sha256;
var unsignedJwtData = Base64UrlEncoder.Encode(Encoding.UTF8.GetBytes(headerString)) + "." + Base64UrlEncoder.Encode(Encoding.UTF8.GetBytes(payloadString));
var signature = dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
return unsignedJwtData + "." + Base64UrlEncoder.Encode(signature);
}
}
但是,当我将WebJob部署到Azure时,我得到以下异常:
Microsoft.Azure.WebJobs.Host.FunctionInvocationException:执行函数时出现异常:NotificationFunctions.QueueOperation ---> System.Security.Cryptography.CryptographicException:系统找不到指定的文件。在System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle提供程序,Byte [] keyBlob,String格式)处于System.Security.Cryptography.CngKey.Import(Byte [] keyBlob,CngKeyBlobFormat格式,CngProvider提供程序)
它说它无法找到指定的文件,但我传入的参数不是在查看文件位置,而是在内存中。根据我收集的内容,我可能需要启用某种加密设置才能使用CngKey.Import方法,但我无法在Azure门户中找到与此相关的任何设置。
我也尝试过使用JwtSecurityTokenHandler,但它似乎没有处理我需要使用的ES256哈希算法(即使它在JwtAlgorithms类中被引用为ECDSA_SHA256)。
任何建议都将不胜感激!
更新
看来CngKey.Import实际上可能正在尝试将证书存储在Azure上无法访问的位置。我不需要存储它,所以如果有更好的方法来访问内存中的证书或将其转换为更容易使用的其他类型的证书。
更新2
此问题可能与Azure Web Apps IIS设置无法按照提及的here加载用户配置文件有关。我已通过在Azure门户应用程序设置中设置WEBSITE_LOAD_USER_PROFILE = 1来启用此功能。我在Azure中通过WebJob和Web App运行代码时尝试过此更新,但仍然收到相同的错误。
答案 0 :(得分:2)
我使用反编译器来了解CngKey.Import方法实际上在做什么。看起来它试图将我正在使用的证书插入“Microsoft软件密钥存储提供程序”。我实际上并不需要这个,只需要读取证书的值,但看起来不可能。
一旦我意识到证书已插入到计算机中的某个商店,我开始考虑如果您的Azure Web App在共享环境中运行,从安全角度来看会有多么糟糕,就像它一样免费和共享层。果然,我的VM在共享层上。将其扩展到Basic层解决了这个问题。