当前位置: 首页 > 知识库问答 >
问题:

对字符串字节执行RSA时出现IllegalBlockSize异常

赫连开畅
2023-03-14

我正在尝试用Java编写RSA加密和解密类,用于客户端来回传递字符串的服务器。我为这些类编写了以下代码:

public class RSAEncryption {
public static final String KEYGENALGORITHM = "RSA";
public static final String ALGORITHM = "RSA/ECB/PKCS1Padding";

public static KeyPairContainer generateKey() {
      KeyPairGenerator keyGen;
      KeyPair key;
    try {
        keyGen = KeyPairGenerator.getInstance(KEYGENALGORITHM);
        keyGen.initialize(1024);
        key = keyGen.generateKeyPair();
        return new KeyPairContainer(key.getPublic(), key.getPrivate());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        System.out.println("Error: No such algorithm");
    }
    return null;
 }

public static String pubkeyToString(PublicKey key){
    byte[] array = key.getEncoded();
    BASE64Encoder encoder = new BASE64Encoder();
    String tempstring = encoder.encode(array);
    return tempstring;
}

public static PublicKey stringToPubKey(String string){
    BASE64Decoder decoder = new BASE64Decoder();
    try {
        byte[] array = decoder.decodeBuffer(string);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(array);
        KeyFactory keyFact = KeyFactory.getInstance(KEYGENALGORITHM);
        PublicKey pubKey = keyFact.generatePublic(x509KeySpec);
        return pubKey;
    } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } return null;
}

public static byte[] rSAencrypt(byte[] plaintext, String keystring) {
    Cipher cipher;
    try {
        PublicKey key = stringToPubKey(keystring);
        cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherText = cipher.doFinal(plaintext);
        //String cipherText = new String(cipherTextbytes);
        return cipherText;
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;

}

public static byte[] rSAdecrypt(byte[] ciphertext, PrivateKey key){
    Cipher cipher;
    try {
        //byte[] ciphertext = ciphertextstring.getBytes();
        cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decryptedText = cipher.doFinal(ciphertext);
        return decryptedText;
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}
}

我有以下测试类代码:

public class RSAEncryptionKeyDemo {
public static void main(String[] args){
    KeyPairContainer keyPair = RSAEncryption.generateKey();
    PublicKey pubKey = keyPair.getPublicKey();
    String pubKeytext = RSAEncryption.pubkeyToString(pubKey);
    System.out.println(pubKeytext);

    String plaintext = "Hello world!";
    byte[] ciphertext = RSAEncryption.rSAencrypt(plaintext.getBytes(), pubKeytext);
    String ciphertextString = new String(ciphertext);
    System.out.println(ciphertextString);

    PrivateKey privkey = keyPair.getPrivateKey();
    byte[] decryptedText = RSAEncryption.rSAdecrypt(ciphertextString.getBytes(), privkey);

    String decryptedTextstring = new String(decryptedText);

    System.out.println(decryptedTextstring);


}
}

然而,当我尝试运行测试类时,密钥生成和加密工作正常,但当我尝试解密时,会出现一个错误。错误是javax。加密。IllegalBlockSizeException:数据不能超过128字节,但我的数据肯定小于128字节。

我可以确认将公钥转换为字符串并返回相同的公钥。我也尝试过只用字节测试代码,效果很好。错误显然是试图解密从字符串中提取的字节。

有没有办法解密字符串中的字节而不抛出这个错误?提前感谢,非常感谢。

编辑:我想我可能已经隔离了这个问题。我试图将加密的字节数组转换为字符串,然后从中提取字节,但是加密的字节数组无论如何都不能正确转换为字符串,所以当我得到字节时,它不能提取原始加密的字节数组。这是正确的吗?如果是,我如何正确地将字节数组转换为字符串,以便我们可以交换它?

共有1个答案

姜志行
2023-03-14

如果你这么做

byte[] ciphertext = RSAEncryption.rSAencrypt(plaintext.getBytes(), pubKeytext);
//String ciphertextString = new String(ciphertext);
//System.out.println(ciphertextString);

PrivateKey privkey = keyPair.getPrivateKey();
byte[] decryptedText = RSAEncryption.rSAdecrypt(ciphertext, privkey);

代码运行得非常好。无法将字节数组转换为字符串,因为字节会转换为字符并返回字节(使用getBytes())——具体取决于默认的字符集<代码>新字符串(密文)删除不可打印的字符,这些字符会更改密文,从而使明文无法恢复。(感谢Artjom B.指出这一点。)

只需使用Base64或二进制传输您的密文,例如:

byte[] ciphertext = RSAEncryption.rSAencrypt(plaintext.getBytes(), pubKeytext);
String ciphertextString = Base64.toBase64String(ciphertext);
System.out.println(ciphertextString);

PrivateKey privkey = keyPair.getPrivateKey();
byte[] decryptedText = RSAEncryption.rSAdecrypt(Base64.decode(ciphertextString), privkey);

(我在这里使用的是BouncyCastle Base64编码器。)

 类似资料:
  • 我正试图通过使用以下方法来取消加密字符串,但遇到了异常。 我试图将我的加密字符串发送到下面的方法,但它不能得到Byte[],在将字符串转换为Byte[]时得到数字格式异常。 请建议。

  • 我从字符串标记器开始,它给我正确的结果,直到我收到上面的字符串作为输入。 此字符串的特殊之处在于,它在几个管道之间没有任何字符,例如和 当我试图用标记器拆分它时,它给我的标记比我预期的要少,它只是忽略了空字符,结果是我给phoneNumber分配了1257值,给RegionCode分配了InsertDaate值。 null

  • 我有一个代表学生实体的字符串: 学生实体类是: 对于解析字符串,我使用以下代码: 响应1是一个httpresponse的主体,它代表我来自描述的字符串。 例外情况:

  • 如何将字符串(字节字符串)转换为字节(字节字符串),而不必手动复制和粘贴字符串并在其前面放置b?

  • 问题内容: 为什么以下算法对我来说不停止?(str是我要搜索的字符串,findStr是我要寻找的字符串) 问题答案: 最后一行造成了问题。永远不会为-1,所以会有无限循环。可以通过将代码的最后一行移到if块中来解决此问题。

  • 我已经读了很多关于这个错误的帖子,但我仍然无法理解。当我尝试循环遍历我的函数时: 以下是错误: