C#使用PKCS8私钥解密JWE遇RSACng已释放对象异常
解决C#中使用PKCS8私钥解密JWE时的"Cannot access a disposed object"异常
核心问题原因
代码抛出Cannot access a disposed object. Object name: 'RSACng'异常,根源在LoadPrivateKeyFromPem方法:
static RSA LoadPrivateKeyFromPem(string privateKeyPem) { using var key = RSA.Create(); // using会在方法结束时自动释放对象 key.ImportFromPem(privateKeyPem); return key; // 返回时对象已被释放,后续使用必然报错 }
using关键字会在代码块结束后自动调用RSA对象的Dispose方法,导致返回的对象处于已释放状态,后续用它创建RsaSecurityKey并解密时就会触发异常。
修正后的完整代码
以下是修复后的代码,同时调整了Token验证参数(仅保留解密所需配置,关闭不必要的验证项):
using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Cryptography; using Microsoft.IdentityModel.Tokens; namespace Transaction { public static class CallDecryptJwe { public static void DecryptJwe(string jweString, string decryptionKeyInput) { string jweToken = jweString; string privateKeyPem = decryptionKeyInput; JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); try { // 加载私钥,用using包裹确保使用完后释放资源 using RSA rsaPrivateKey = LoadPrivateKeyFromPem(privateKeyPem); var rsaSecurityKey = new RsaSecurityKey(rsaPrivateKey); var validationParameters = new TokenValidationParameters { TokenDecryptionKey = rsaSecurityKey, // 仅需解密JWE,关闭其他验证项 ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false }; // 解密并处理JWE var claimsPrincipal = handler.ValidateToken(jweToken, validationParameters, out var securityToken); Console.WriteLine("解密后的Claims:"); foreach (var claim in claimsPrincipal.Claims) { Console.WriteLine($"{claim.Type}: {claim.Value}"); } // 直接获取明文JSON(可选) if (securityToken is JwtSecurityToken jwtToken) { Console.WriteLine("\n明文JSON内容:"); Console.WriteLine(jwtToken.Payload.SerializeToJson()); } } catch (Exception ex) { Console.WriteLine($"错误信息: {ex.Message}"); Console.WriteLine($"异常详情: {ex.ToString()}"); } } static RSA LoadPrivateKeyFromPem(string privateKeyPem) { // 移除using,由调用方负责释放RSA对象 RSA key = RSA.Create(); key.ImportFromPem(privateKeyPem); return key; } } }
额外验证点
- 密钥格式确认:你的PKCS8私钥格式正确,
ImportFromPem可直接加载,无需额外转换。 - 算法匹配:JWE头部指定的
RSA-OAEP-256算法,RsaSecurityKey默认支持,无需额外配置。 - 资源管理:调用
LoadPrivateKeyFromPem时用using包裹RSA对象,确保解密完成后正确释放加密资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Adam Williams
相关产品推荐
相关产品推荐

