Pycryptodome与Java的RSA PKCS#1 OAEP SHA256互操作性问题
解决Python RSA加密后Java解密报BadPaddingException的问题
这个问题我之前碰到过,核心原因是Python和Java两端的OAEP填充参数不匹配,具体是MGF1(掩码生成函数)使用的哈希算法不一致导致的,下面给你两种可行的解决思路:
方案一:修改Java代码(推荐,更安全)
Java的RSA/ECB/OAEPWithSHA-256AndMGF1Padding算法标识符很容易误导人——它指定了OAEP用SHA-256,但Sun/Oracle的JCE实现默认会给MGF1用SHA-1,而你的Python代码里MGF1默认用的是和OAEP一致的SHA-256,这就导致了参数不匹配。
我们可以通过OAEPParameterSpec显式指定MGF1也使用SHA-256,和Python端对齐:
import java.security.spec.MGF1ParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; // ... 其他代码 ... Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); // 明确指定OAEP哈希、MGF1算法及MGF1的哈希 OAEPParameterSpec oaepParams = new OAEPParameterSpec( "SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT ); cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams); byte[] cek = cipher.doFinal(ciphertext);
方案二:修改Python代码(适配Java默认行为)
如果因为业务限制不能修改Java代码,你可以调整Python端的MGF1哈希算法为SHA-1,匹配Java的默认配置:
from Crypto.Cipher import PKCS1_OAEP from Cryptodome.Hash import SHA256, SHA1 cipher = PKCS1_OAEP.new( key=self.key, hashAlgo=SHA256, mgfHash=SHA1 # 显式指定MGF1用SHA-1 ) ciphertext = cipher.encrypt(cek)
额外排查点
除了参数匹配问题,你还可以快速确认以下两点:
- 确保加密用的公钥和解密用的私钥是同一密钥对,别搞混了不同的密钥
- 确认加密的明文
cek长度不超过RSA密钥的最大允许长度:对于2048位RSA+SHA256,最大明文长度是2048/8 - 2*32 - 2 = 190字节,过长的明文也会导致填充错误
内容的提问来源于stack exchange,提问作者Alastair McCormack




