如何在不获取CryptographicException的情况下在Azure WebJob上签署JWT令牌?

我有一个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: Exception while executing function: NotificationFunctions.QueueOperation —> System.Security.Cryptography.CryptographicException: The system cannot find the file specified. at System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle provider, Byte[] keyBlob, String format) at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider)

它说它找不到指定的文件,但我传入的参数没有查看文件位置,它们在内存中.根据我收集的内容,可能需要启用某种加密设置才能使用CngKey.Import方法,但我无法在Azure门户中找到与此相关的任何设置.

我也尝试过使用JwtSecurityTokenHandler,但它似乎没有处理我需要使用的ES256哈希算法(即使它在JwtAlgorithms类中被引用为ECDSA_SHA256).

任何建议,将不胜感激!

UPDATE

看起来CngKey.Import实际上可能正在尝试将证书存储在Azure上无法访问的位置.我不需要它存储,所以如果有更好的方法来访问内存中的证书或将其转换为更容易使用的其他类型的证书.

更新2

此问题可能与Azure Web Apps IIS设置无法加载如here所述的用户配置文件有关.我已通过在Azure门户应用程序设置中设置WEBSITE_LOAD_USER_PROFILE = 1来启用此功能.我通过WebJob和Azure中的Web应用程序运行代码时尝试过此更新但我仍然收到相同的错误.

最佳答案 我用一个反编译器来了解CngKey.Import方法实际上在做什么.看起来它试图将我正在使用的证书插入“Microsoft软件密钥存储提供程序”.我实际上并不需要这个,只需要读取证书的值,但看起来不可能.

一旦我意识到证书被插入到机器的某个地方的某个商店,我开始考虑如果你的Azure Web App在共享环境中运行,从安全的角度来看会有多么糟糕,就像免费的那样和共享层.果然,我的VM在共享层上.将其扩展到Basic层可以解决此问题.

点赞