我在使用Java中的RSA解密数据(或者也可能是加密错误)时遇到问题。 我想用String中的更多信息加密公钥,然后解密这个公钥并用它加密(我使用2048 RSA):
加密:
public void saveExportToFile(String fileName, BigInteger mod, BigInteger exp, String info, PublicKey puk) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(baos));
try {
oout.writeObject(mod);
oout.writeObject(exp);
oout.writeChars(info);
oout.close();
baos.close();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, puk);
FileOutputStream fos = new FileOutputStream(new File(fileName));
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] data = baos.toByteArray();
int i = 0;
byte[] buffer = new byte[128];
byte[] cipherData = null;
while (i < data.length) {
if (i+128 >= data.length) {
buffer = new byte[data.length - i];
System.arraycopy(data, i, buffer, 0, data.length - i);
cipherData = cipher.doFinal(buffer);
bos.write(cipherData);
} else {
System.arraycopy(data, i, buffer, 0, 128);
cipherData = cipher.doFinal(buffer);
bos.write(cipherData);
}
i += 128;
}
bos.close();
} catch (Exception e) {
throw new IOException("Unexpected error", e);
}
}
解密:
public void getDataFromRSA(String sendname, PrivateKey privateKey) {
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sendname)));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
int length = 0;
int allLength = 0;
byte[] buffer = new byte[128];
byte[] bufferAC = null;
byte[] outData = null;
byte[] allData = null;
byte[] tmpData = null;
while ( (length = bis.read(buffer)) != -1) {
if (length < 128) {
bufferAC = new byte[length];
System.arraycopy(buffer, 0, bufferAC, 0, length);
outData = cipher.doFinal(bufferAC);
} else {
outData = cipher.doFinal(buffer); // HERE IS THE ERROR
}
allLength += outData.length;
tmpData = allData;
allData = new byte[allLength];
System.arraycopy(tmpData, 0, allData, 0, tmpData.length);
System.arraycopy(outData, 0, allData, tmpData.length, outData.length);
}
} catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | ClassNotFoundException | InvalidKeySpecException e) {
e.printStackTrace();
}
}
修改 好吧,我似乎并不像我想的那样了解加密。我只想使用RSA(如果可能的话),因为我不需要多次传输信息(信息大小各不相同)。我编辑了这样的加密:
int i = 0;
byte[] buffer = new byte[245];
byte[] cipherData = null;
while (i < data.length) {
if (i+245 >= data.length) {
buffer = new byte[data.length - i];
System.arraycopy(data, i, buffer, 0, data.length - i);
} else {
System.arraycopy(data, i, buffer, 0, 245);
}
cipherData = cipher.update(buffer);
bos.write(cipherData);
i += 245;
}
bos.write(cipher.doFinal()); // HERE IS THE ERROR
bos.close();
现在我得到javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
(为缓冲区大小尝试了几个较低的值)。是因为数据长度不是blocksize的倍数?这可以解决吗?谢谢你的回答。
答案 0 :(得分:3)
首先,您应该使用混合加密,即首先使用对称密码加密数据,然后使用RSA密钥加密随机密钥 - 将两者都发送到接收方。
其次,您不应该在循环中为单个消息执行doFinal
。请改用update
和一个doFinal
。
第三,2048位是256字节。只要您继续尝试解密128个字节而不是256个字节,您将获得此异常。通常我使用2048 / Byte.SIZE
代替它,它使代码更具可读性并避免错误。
答案 1 :(得分:0)
当您尝试使用私钥加密数据并使用公钥解密时,会发生此异常,您需要撤消此操作,或者必须使用单个密钥来加密和解密数据。这将解决此异常。