C#中使用A128CBC_HS256加密生成JWT Token时解密失败的问题排查
C#中使用A128CBC_HS256加密生成JWT Token时解密失败的问题排查
看起来你的代码存在几个容易混淆的点,导致你误以为解密流程失败,我来逐一拆解分析:
1. 先解决编译层面的错误
你的Main方法里有个明显的语法问题:
MyModel model = new { Email = "mail@mail.com", Phone = "987373721", Amt = 1000 };
MyModel是未定义的类型,匿名类型应该用var声明:
var model = new { Email = "mail@mail.com", Phone = "987373721", Amt = 1000 };
另外,你需要在代码顶部添加using System.Text.Json;,否则JsonSerializer会无法识别。
2. 对JWT.Decode返回值的误解
在你的Encrypt方法中,其实已经正确完成了解密,但你可能没注意到结果的形式:
- 你加密的是JSON字符串的字节数组,所以
JWT.Decode返回的是原始的JSON字符串,而不是直接的MyModel对象。 - 如果你想得到原模型对象,需要对解密后的字符串再做一次反序列化:
string ptext = JWT.Decode(encrypted, key, JweAlgorithm.A256KW, JweEncryption.A128CBC_HS256); // 注意:这里需要定义MyModel实体类,或者用匿名类型反序列化 var decodedModel = JsonSerializer.Deserialize<MyModel>(ptext); - 你可以在代码里添加输出验证,确认解密结果和原输入一致:
Console.WriteLine("原输入:" + input); Console.WriteLine("解密结果:" + ptext); Console.WriteLine("是否匹配:" + (input == ptext)); // 正常情况下会输出True
3. 在线JWT工具的局限性
如果你尝试用在线JWT解析工具解密你的加密字符串,大概率会失败——因为绝大多数在线工具只支持JWS(带签名的JWT),不支持JWE(加密的JWT)。JWE是加密后的密文,无法被仅支持JWS的工具解析,这会让你误以为代码解密失败,但实际上你的代码内部的JWT.Decode调用是完全正常的。
4. 你的密钥和算法配置是正确的
你的Digest方法将64位十六进制字符串转成32字节(256位)密钥的逻辑是对的:
A256KW密钥包装算法正好需要256位密钥A128CBC_HS256加密算法需要256位密钥(拆分后128位用于AES加密,128位用于HMAC验证)
这部分没有问题。
修正后的完整测试代码片段
using Jose; using System.Text; using System.Text.Json; public class MyProgram { public byte[] Digest() { string semkey = "dc5f7ad6cb89f1254696932d40d19ac079c14e8b3113351e48f5d6cf21263f4f"; int len = semkey.Length / 2; byte[] val = new byte[len]; for (int i = 0; i < len; i++) { int index = i * 2; string hexByte = semkey.Substring(index, 2); val[i] = Convert.ToByte(hexByte, 16); } return val; } public string Encrypt(string input) { byte[] key = Digest(); byte[] payload = Encoding.UTF8.GetBytes(input); string encrypted = JWT.Encode(payload, key, JweAlgorithm.A256KW, JweEncryption.A128CBC_HS256); // 验证解密流程 string ptext = JWT.Decode(encrypted, key, JweAlgorithm.A256KW, JweEncryption.A128CBC_HS256); Console.WriteLine("解密后的明文:" + ptext); Console.WriteLine("与原输入是否一致:" + (ptext == input)); return encrypted; } public static void Main() { var model = new { Email = "mail@mail.com", Phone = "987373721", Amt = 1000 }; string data = JsonSerializer.Serialize(model); MyProgram p = new MyProgram(); string enc_token = p.Encrypt(data); } } // 需要定义对应的实体类用于反序列化(可选) public class MyModel { public string Email { get; set; } public string Phone { get; set; } public int Amt { get; set; } }
运行这段代码后,你会在控制台看到解密后的明文和原输入完全一致,说明整个加密解密流程是正常的。
内容来源于stack exchange
相关产品推荐
相关产品推荐

