Java服务端RSA加密后浏览器Web Crypto API解密失败问题排查
RSA跨端加解密失败根因
核心问题:两端加密填充规则不兼容
- 前端Web Crypto API使用
RSA-OAEP算法配合SHA-256哈希做加密填充 - Java服务端
Cipher.getInstance("RSA")默认使用RSA/ECB/PKCS1Padding填充规则,两者完全不匹配,是解密失败的直接原因。
你补充的调研结果也可以验证该判断:Web Crypto自身生成的密文加解密算法一致,所以可以正常解密;填充规则不匹配的前提下,修改返回数据格式不会解决问题。
修复方案
方案1:Java服务端适配前端算法(推荐,安全性更高)
明确指定Java加密算法和填充规则与前端完全一致,额外显式配置MGF1参数避免不同JDK默认规则差异:
import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import java.security.spec.MGF1ParameterSpec; // 原有公钥生成逻辑保持不变 Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams); // 后续加密逻辑保持不变
方案2:前端适配Java默认填充规则(不推荐,安全性更低)
修改前端密钥生成、解密的算法配置为Java默认的RSAES-PKCS1-v1_5:
// 密钥生成阶段修改算法名称 const key = await window.crypto.subtle.generateKey( { name: 'RSAES-PKCS1-v1_5', modulusLength: 512, publicExponent: new Uint8Array([1, 0, 1]), }, true, ['encrypt', 'decrypt'], ) // 解密阶段同步修改算法名称 await window.crypto.subtle.decrypt( { name: 'RSAES-PKCS1-v1_5' }, key.privateKey, bytes.buffer, );
注意:示例中使用的512位RSA密钥仅可用于本地调试,生产环境必须使用2048位及以上长度的RSA密钥,否则存在极高的被破解风险。
内容的提问来源于stack exchange,提问作者Lee Jeonghyun
相关产品推荐
相关产品推荐

