Java中RSA解密出现BadPaddingException问题求助
问题分析与解决:C# RSA加密AES密钥后Java解密抛出BadPaddingException
核心错误:AES密钥的字节转换逻辑错误
你在C#中生成AES密钥时,已经将二进制密钥转换为Base64字符串返回,但加密时却把这个Base64字符串当成普通文本用Encoding.UTF8.GetBytes()转成字节数组——这相当于加密的是Base64文本内容,而非原始的AES二进制密钥。这种错误的转换会导致加密后的内容不符合PKCS1Padding规范,直接触发Java端的BadPaddingException。
修正后的C#加密代码(原生RSACryptoServiceProvider版本)
public string Encrypt(string plainAesKey) { string publicKeyFileName = publicKeyPath; string cipherText = string.Empty; using (var rsa = new RSACryptoServiceProvider()) { var param = getCertificate(publicKeyFileName); rsa.ImportParameters(param); // 关键修正:将Base64字符串解码为原始AES二进制密钥,而非转UTF8字节 var plainTextBytes = Convert.FromBase64String(plainAesKey); byte[] cipherTextBytes = rsa.Encrypt(plainTextBytes, RSAEncryptionPadding.Pkcs1); cipherText = Convert.ToBase64String(cipherTextBytes); } return cipherText; }
修正后的C#加密代码(BouncyCastle版本)
static string contentRootPath = "Content"; string publicKeyPath = Path.Combine(contentRootPath, "RSAKeys", "publicKey.cer"); public string EncryptDataWithBouncyCastle(string aesKey) { string publicFilePath = publicKeyPath; try { using (FileStream fs = File.OpenRead(publicFilePath)) { X509CertificateParser parser = new X509CertificateParser(); X509Certificate certificate = parser.ReadCertificate(fs); RsaKeyParameters publicKey = (RsaKeyParameters)certificate.GetPublicKey(); var rsaCipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding"); rsaCipher.Init(true, publicKey); // 关键修正:解码Base64得到原始AES密钥字节 byte[] aesKeyBytes = Convert.FromBase64String(aesKey); byte[] EncData = rsaCipher.DoFinal(aesKeyBytes); return Convert.ToBase64String(EncData); } } catch (Exception e) { return e.Message.ToString(); } }
其他可能导致BadPaddingException的原因及排查步骤
密钥对不匹配
确认C#加密使用的公钥与Java解密使用的私钥属于同一RSA密钥对。可以用公钥加密一段简单文本(如"test"),再用私钥解密,验证是否能正常得到明文。公钥提取错误
检查getCertificate方法是否正确从.cer文件中提取公钥。标准的X.509证书公钥提取代码示例:private RSAParameters getCertificate(string publicKeyFileName) { X509Certificate2 cert = new X509Certificate2(publicKeyFileName); using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PublicKey.Key) { return rsa.ExportParameters(false); } }Java端Cipher配置问题
确保Java端的Cipher算法与C#完全一致。部分JCE提供者可能需要明确指定提供者,可尝试修改为:Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "SunJCE");Base64编码/解码不一致
确认C#生成的Base64字符串没有额外的换行或空格,Java端使用Base64.decodeBase64()能正确解码。如果C#生成的Base64带有换行,需先去除后再传递给Java。
验证步骤
- 用修正后的C#代码加密AES密钥,得到加密后的Base64字符串。
- 在Java端解密该字符串,确认得到32字节的原始AES密钥(AES256密钥长度固定为32字节)。
- 用该AES密钥加密一段测试文本,再用Java解密,验证整个流程是否正常。
内容的提问来源于stack exchange,提问作者imshubhamlack
相关产品推荐
相关产品推荐

