解密后的BigInteger如何转换回原字符串?RSA加密场景技术问询
解决RSA解密后BigInteger转回原字符串失败的问题
我太懂这种卡壳的感觉了——加密前明明能轻松把BigInteger转回原字符串,结果解密后拿到的BigInteger就像变了个“假的”,怎么转都不对。别慌,我踩过类似的坑,大概率是这几个细节没处理好,咱们一步步来解决:
常见问题原因&解决方案
1. 字符编码不统一
这是最容易忽略的点!加密前你把字符串转字节数组用的是A编码,解密后转字符串用了B编码,结果肯定乱码或者转不出原内容。
解决办法:全程固定用同一种编码(比如UTF-8,别用系统默认编码),代码里明确指定:
// 加密前转字节数组 byte[] originalBytes = originalStr.getBytes(StandardCharsets.UTF_8); // 解密后转字符串 String recoveredStr = new String(recoveredBytes, StandardCharsets.UTF_8);
2. BigInteger的符号位搞砸了
如果原字符串的字节数组里有高位字节(比如第一个字节是0x80及以上),直接用new BigInteger(byteArray)会把它当成负数的补码,导致解密后的BigInteger是负数,转字节数组时完全不是原来的内容。
解决办法:创建BigInteger时明确指定符号位为1(正数):
// 加密前:用1标记为正数,避免符号位干扰 BigInteger plaintext = new BigInteger(1, originalBytes);
这样解密后得到的BigInteger肯定是正数,转字节数组时才会和原内容匹配。
3. 前导零丢失/多余
BigInteger会自动忽略字节数组里的前导零,但如果原字符串的字节数组本来就有前导零(比如某些特殊字符或二进制数据),解密后转字节数组时就会丢失这些前导零,导致转字符串失败。
解决办法:
- 如果是普通文本字符串:一般不会有前导零,直接解密后检查并移除可能的前导零即可:
byte[] recoveredBytes = decryptedBigInt.toByteArray(); // 移除前导零(如果有的话) if (recoveredBytes.length > 0 && recoveredBytes[0] == 0) { byte[] temp = new byte[recoveredBytes.length - 1]; System.arraycopy(recoveredBytes, 1, temp, 0, temp.length); recoveredBytes = temp; }
- 如果是二进制数据或有前导零的内容:可以先把字节数组转成Base64字符串,再转BigInteger,这样就不会丢失任何信息:
// 加密前 String base64Str = Base64.getEncoder().encodeToString(originalBytes); BigInteger plaintext = new BigInteger(base64Str.getBytes(StandardCharsets.UTF_8)); // 解密后 String recoveredBase64 = new String(decryptedBigInt.toByteArray(), StandardCharsets.UTF_8); byte[] recoveredBytes = Base64.getDecoder().decode(recoveredBase64); String recoveredStr = new String(recoveredBytes, StandardCharsets.UTF_8);
完整可运行示例代码
给你写了个完整的流程,把上面的坑都填上了,你可以直接参考:
import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.KeyPairGenerator; import javax.crypto.Cipher; import java.util.Base64; public class RSAStrConverter { public static void main(String[] args) throws Exception { // 生成2048位RSA密钥对 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(2048); KeyPair keyPair = keyGen.generateKeyPair(); String originalStr = "测试RSA加密解密:Hello, 世界!"; System.out.println("原字符串:" + originalStr); // === 加密流程 === byte[] originalBytes = originalStr.getBytes(StandardCharsets.UTF_8); // 用正数符号位创建BigInteger BigInteger plaintext = new BigInteger(1, originalBytes); // RSA加密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); byte[] encryptedBytes = cipher.doFinal(plaintext.toByteArray()); BigInteger ciphertext = new BigInteger(encryptedBytes); // === 解密流程 === cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); byte[] decryptedBytes = cipher.doFinal(ciphertext.toByteArray()); BigInteger decryptedBigInt = new BigInteger(decryptedBytes); // 转换回字符串(处理前导零) byte[] recoveredBytes = decryptedBigInt.toByteArray(); if (recoveredBytes.length > 0 && recoveredBytes[0] == 0) { recoveredBytes = java.util.Arrays.copyOfRange(recoveredBytes, 1, recoveredBytes.length); } String recoveredStr = new String(recoveredBytes, StandardCharsets.UTF_8); System.out.println("恢复的字符串:" + recoveredStr); } }
内容的提问来源于stack exchange,提问作者Ras
相关产品推荐
相关产品推荐

