解密JSEncrypt加密数据时遇BadPaddingException问题求助
问题分析与错误修正
核心错误:RSA密钥逻辑完全颠倒
RSA的标准逻辑是公钥加密、私钥解密,你的代码完全搞反了:
- 客户端:加载私钥后调用
encrypt(),用私钥加密明文,这违背了RSA的安全设计(私钥应仅在服务端保存,客户端只能持有公钥) - 服务端:传入
PublicKey执行解密操作,公钥无法解密用公钥加密的内容,这在RSA机制里是不可能实现的
客户端代码的其他问题
response.text()异步处理错误response.text()返回的是Promise对象,直接赋值给p.textContent会显示[object Promise],正确写法需等待Promise兑现:.then(response => response.text()) .then(text => { var main = document.querySelector("main"); var p = document.createElement("h1"); p.textContent = text; main.appendChild(p); })- 密钥使用逻辑错误
客户端应加载公钥而非私钥,调用encryptor.setPublicKey(publicKey)后再加密明文,私钥绝对不能暴露给客户端。
服务端代码的问题
- 缺失Base64解码步骤
JSEncrypt的encrypt()返回的是Base64编码的字符串,服务端拿到的token参数是Base64格式,必须先解码为字节数组才能解密,直接使用原始参数转字节数组会导致解密失败。 - 不必要且错误的分块解密
对于JSEncrypt默认的RSA_PKCS1_PADDING填充方式,cipher.doFinal()可以直接处理完整密文,手动分块的逻辑完全多余,且分块规则不符合RSA解密的要求。 - 密钥类型错误
服务端解密必须使用PrivateKey,需将方法参数改为PrivateKey privateKey,并在初始化Cipher时传入私钥。
修正后的核心代码示例
客户端修正(使用公钥加密)
reader.onloadend = function (e) { var publicKey = e.target.result; // 加载公钥文件 var encryptor = new JSEncrypt(); encryptor.setPublicKey(publicKey); var encryptedText = encryptor.encrypt(plainText); const params = new URLSearchParams(); params.append('token', encryptedText); fetch(form.action, { method: form.method, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params }) .then(response => response.text()) .then(text => { var main = document.querySelector("main"); var p = document.createElement("h1"); p.textContent = text; main.appendChild(p); }) .catch(error => { var main = document.querySelector("main"); var p = document.createElement("h1"); p.textContent = error.message; main.appendChild(p); }); };
服务端修正(使用私钥解密,处理Base64)
import java.util.Base64; import java.security.PrivateKey; import javax.crypto.Cipher; public class RSADecryptor { public static String decrypt(String base64CipherText, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); // 解码Base64格式的密文 byte[] cipherText = Base64.getDecoder().decode(base64CipherText); // 直接解密完整密文 byte[] decryptedBytes = cipher.doFinal(cipherText); return new String(decryptedBytes); } }
内容的提问来源于stack exchange,提问作者Kleber Mota
相关产品推荐
相关产品推荐

