У меня проблема с расшифровкой (или, может быть, неправильно шифрования, тоже) данных с RSA в Java. Я хочу шифрует открытый ключ еще некоторую информацию в строку, а затем расшифровать этот открытый ключ и шифрует с ней что-то (я использую 2048 RSA):Ошибка в расшифровке RSA Java данных: javax.crypto.BadPaddingException: дешифрование ошибка
Шифрование:
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();
}
}
EDIT ОК, мне кажется, я не знаю о шифровании столько, сколько я думал. Я бы хотел использовать только 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
(пробовал несколько меньшие значения для размера буфера). Это потому, что длина данных не кратно блокам? Может ли это быть исправлено? Спасибо за ответы.
Вы не должны использовать RSA в качестве блочного шифрования. В вашей схеме злоумышленник может просто вставить предыдущий блок в любом месте вашего шифра, не заметив его во время дешифрования. Гибридное шифрование/дешифрование не так уж сложно, почему бы вам не сделать попытку сделать это правильно? –
Для вашей текущей проблемы: у RSA есть накладные расходы, вы должны вложить не более 245 байтов и дешифровать на 256 байт (11 байт накладных расходов). Если необходимо, используйте doFinal в цикле с 245-байтовым буфером шифрования и буфером * для ввода * байта в 256 байт. Обратите внимание, что это не исправляет ваш протокол, а только вашу текущую реализацию. –
Спасибо, я использую гибридную криптографию сейчас без проблем – d3im