You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解密后的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:08:42