gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 11:19:03 24 4
gpt4 key购买 nike

我正在尝试用 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);


}
}

但是,当我尝试运行测试类时, key 生成和加密工作正常,但当我尝试解密时会抛出错误。错误是javax.crypto.IllegalBlockSizeException:数据不能长于128字节,但是我的数据肯定小于128字节。

我可以确认将公钥转换为字符串并返回会返回相同的公钥。我也尝试过仅使用字节来测试代码,效果很好。该错误显然是在尝试解密从字符串中获取的字节时发生的。

是否有某种方法可以解密从字符串中获取的字节而不引发此错误?预先感谢,非常感谢。

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

最佳答案

如果你这样做

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()) - 取决于您的默认字符集。 new String(ciphertext) 删除不可打印的字符,从而更改密文,从而使明文无法恢复。 (感谢 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 编码器。)

关于java - 对字符串字节执行 RSA 时出现 IllegalBlockSize 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31467532/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com