Java生成RSA密钥对后Node加密Java解密报错如何解决?
RSA跨端加解密报错根因与修复方案
两个报错的直接原因
1. javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes
RSA加密后的输出为二进制buffer,长度和密钥长度严格匹配(1024位RSA加密后固定128字节,2048位固定256字节)。直接传输二进制密文时,HTTP协议默认会按字符串规则解析请求体,导致二进制字节被篡改、长度异常,Java侧拿到的密文长度不符合RSA块大小要求,触发该错误。
2. javax.crypto.BadPaddingException: Decryption error
90%以上的该类报错是两端RSA填充规则不匹配导致,剩余为密钥格式、Base64编解码不匹配问题:
- Node.js
crypto.publicEncrypt方法默认填充为RSA_PKCS1_OAEP_PADDING,而Java RSA默认填充为RSA/ECB/PKCS1Padding,填充规则不一致导致解密时无法识别填充位 - Node.js侧未将Base64编码的X.509公钥包装为标准PEM格式,公钥识别失败,加密生成的密文本身非法
- 两端Base64编解码规则不一致(比如一端用标准Base64,另一端用URL安全Base64),密文解码后二进制内容错误
具体修复步骤
- 统一两端填充规则,推荐显式指定不要依赖默认值
Node.js侧加密代码示例:
Java侧解密代码示例:const crypto = require('crypto'); // 必须给纯Base64公钥补全PEM格式头尾,否则crypto无法识别X.509公钥 const rsaPublicKey = `-----BEGIN PUBLIC KEY----- ${Java端生成的Base64编码公钥字符串} -----END PUBLIC KEY-----`; // 加密时显式指定和Java端一致的PKCS1填充 const encryptedBuffer = crypto.publicEncrypt({ key: rsaPublicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from(待加密的密码, 'utf8')); // 加密后转标准Base64字符串再传输 const encryptedPassword = encryptedBuffer.toString('base64');import java.util.Base64; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; // 1. 先解码前端传的Base64密文 byte[] encryptedBytes = Base64.getDecoder().decode(前端传入的encryptedPassword); // 2. 显式指定和前端一致的填充规则 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, 你的PKCS8格式私钥对象); // 3. 解密得到原始密码 byte[] decryptedBytes = cipher.doFinal(encryptedBytes); String originalPassword = new String(decryptedBytes, StandardCharsets.UTF_8); - 额外校验点
- 确认密钥长度:1024位RSA最大支持加密117字节明文,2048位最大支持245字节,普通密码长度都在限制范围内,无需分段加密
- 确认Base64规则:两端都用标准Base64编解码,不要混用URL安全Base64
内容的提问来源于stack exchange,提问作者Bopsi
相关产品推荐
相关产品推荐

