Android与纯Java的RSA/OAEP加密解密不兼容问题求助
解决Android RSA OAEP加密与纯Java解密不兼容的问题
你遇到的核心问题是Android和标准Java对RSA OAEP填充的默认参数实现不一致,导致加密解密无法匹配。虽然PKCS1Padding因为参数简单能正常工作,但OAEP涉及哈希函数和MGF1参数的默认值差异,这是解密失败的关键。
问题根源
Android的Cipher.getInstance("RSA/ECB/OAEPWithAndMGF1Padding")其实是RSA/ECB/OAEPWithSHA-1AndMGF1Padding的简写,而标准Java环境中,这个简写对应的默认哈希算法可能和Android不一致(比如部分Java版本默认使用SHA-256,或者对算法字符串的解析逻辑不同)。即使你尝试指定RSA/ECB/OAEPWithSHA-256AndMGF1Padding,如果没有明确指定参数,两端的Cipher仍可能使用不同的MGF1参数细节,导致解密失败。
解决方案:强制统一OAEP参数
要解决这个问题,需要在两端明确指定完整的OAEP参数,消除默认值的歧义。以下是修改后的代码:
Android端加密代码(修改后)
import android.util.Base64; import java.security.spec.MGF1ParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; public static String encryptMessage(final String plainText, final PublicKey publicKey) throws Exception { // 使用完整的算法名称,同时手动指定参数确保一致性 Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); // 明确指定OAEP的哈希算法、MGF1算法及参数,与Java端完全对齐 OAEPParameterSpec oaepParams = new OAEPParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT ); cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams); return Base64.encodeToString(cipher.doFinal(plainText.getBytes()), Base64.NO_WRAP); }
纯Java端解密代码(修改后)
import java.util.Base64; import java.security.spec.MGF1ParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; public static String decryptMessage(final String encryptedText, final PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); // 与Android端完全相同的OAEP参数配置 OAEPParameterSpec oaepParams = new OAEPParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT ); cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams); Base64.Decoder decoder = Base64.getDecoder(); byte[] byteArray = decoder.decode(encryptedText); byte[] decryptedArray = cipher.doFinal(byteArray); String plainText = new String(decryptedArray); return plainText; }
额外排查点
- 验证Base64一致性:虽然你用PKCS1Padding能正常解密,说明Base64编码解码没有问题,但可以临时打印加密后的字符串,对比Android端输出和Java端接收的字符串是否完全一致,排除传输过程中的编码损坏。
- 确认密钥配对:确保加密用的公钥和解密用的私钥是同一密钥对生成的(这点你用PKCS1能解密已经基本验证,但可以再确认一次)。
- JCE支持性:如果使用SHA-256以外的哈希算法,需要确保两端的JCE(Java加密扩展)都支持该算法(SHA-256是主流环境都支持的,一般没问题)。
内容的提问来源于stack exchange,提问作者user1443721
相关产品推荐
相关产品推荐

