导入RSA公钥Modulus和Exponent时触发「Bad Data」错误,求JWE生成流程及C#代码问题排查
问题分析与解决方案
首先,你遇到的Bad Data异常核心原因是:你直接将mod和exp的ASCII编码字节赋值给了RSAParameters的Modulus和Exponent属性,但RSACryptoServiceProvider期望的是这些大整数对应的原始字节数组(大端字节序),而不是字符串本身的ASCII编码。
Java中的BigInteger可以直接解析十进制格式的密钥参数字符串并正确处理字节转换,但C#的RSAParameters要求的是原始的密钥材料字节,所以你需要先把这些十进制字符串转换为大整数,再导出符合要求的字节数组。
第一步:修正RSA公钥导入的代码
你需要将十进制的mod和exp字符串转换为BigInteger,再转为字节数组(注意要去掉BigInteger自带的符号位,因为公钥参数都是正数)。修正后的代码如下:
using System.Numerics; using System.Security.Cryptography; // 处理Modulus:十进制字符串转BigInteger,再转字节数组(去掉符号位并调整字节序) BigInteger modBigInt = BigInteger.Parse(mod); byte[] modBytes = modBigInt.ToByteArray(); // BigInteger.ToByteArray()会包含符号位,公钥模数是正数,若最后一位是0则移除 if (modBytes[modBytes.Length - 1] == 0) { Array.Resize(ref modBytes, modBytes.Length - 1); } // 反转字节数组:BigInteger是小端序,RSA要求大端序 Array.Reverse(modBytes); // 处理Exponent:同样的逻辑 BigInteger expBigInt = BigInteger.Parse(exp); byte[] expBytes = expBigInt.ToByteArray(); if (expBytes[expBytes.Length - 1] == 0) { Array.Resize(ref expBytes, expBytes.Length - 1); } Array.Reverse(expBytes); // 导入RSA参数 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); RSAParameters rsaKeyInfo = new RSAParameters(); rsaKeyInfo.Modulus = modBytes; rsaKeyInfo.Exponent = expBytes; rsa.ImportParameters(rsaKeyInfo);
第二步:完整的JWE生成流程(使用Jose.Jwt库)
修正公钥导入后,你可以用Jose.Jwt库生成符合要求的JWE,完整示例如下:
using Jose; using System.Text; using System.Collections.Generic; // 你的Payload JSON字符串 string payloadJson = "{\"your\":\"payload\",\"fields\":\"here\"}"; byte[] payloadBytes = Encoding.UTF8.GetBytes(payloadJson); // 生成JWE,指定算法并添加kid头 string jwe = JWT.Encode( payloadBytes, rsa, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM, extraHeaders: new Dictionary<string, object> { { "kid", kid } } );
额外补充
- 为什么Java可以直接用?因为Java的
RSAPublicKeySpec接受BigInteger类型的mod和exp,而Java的BigInteger可以直接解析十进制字符串,内部会自动处理字节序和格式转换,不需要手动调整。 - 如果你使用的是.NET Core/.NET 5+,建议优先使用
RSA.Create()而非RSACryptoServiceProvider——后者是旧的.NET Framework专属类,前者更适配现代.NET的API设计。
内容的提问来源于stack exchange,提问作者riki
相关产品推荐
相关产品推荐

