#java #криптография #шифрование #aes
Использую шифрование AES с разными режимами (далее в примере режим "CBC"). Зашифровываю
следующий файл с текстом.
Вношу ошибку в получившийся шифрованный код примерно в середине текста.
При дешифровке получается следующий текст.
Собственно вопрос: почему неправильно расшифровывается именно этот отрезок текста,
ведь как я понял из документации AES (и как мне объяснял преподаватель) неправильно
расшифровываться должен весь текст, содержащийся после внесенной ошибки? Как сделать,
чтобы работало именно так?
Код класса (в "mode" передаю режим):
public class AesCipher {
private static final String INIT_VECTOR = "ItIsOurBigSecret";
// зашифрование
static byte[] encrypt(byte[] secretKey, byte[] plainText, String mode) {
try {
if (!isKeyLengthValid(secretKey)) {
throw new Exception("Длина ключа должна быть 128, 192 или 256 бит!");
}
IvParameterSpec ivParameterSpec = new IvParameterSpec(INIT_VECTOR.getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "AES");
Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
if (mode.equals("ECB"))
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
else
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher.doFinal(plainText);
} catch (Throwable cause) {
System.out.print(cause.getMessage());
}
return null;
}
// дешифрование
static byte[] decrypt(byte[] secretKey, byte[] cipherText, String mode) {
try {
if (!isKeyLengthValid(secretKey)) {
throw new Exception("Длина ключа должна быть 128, 192 или 256 бит!");
}
IvParameterSpec ivParameterSpec = new IvParameterSpec(INIT_VECTOR.getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "AES");
Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
if (mode.equals("ECB"))
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
else
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher.doFinal(cipherText);
} catch (Throwable cause) {
System.out.print(cause.getMessage());
Controller.ShowMessage(cause.getMessage());
}
return null;
}
// проверка длины ключа
private static boolean isKeyLengthValid(byte[] key) {
return key.length == 16 || key.length == 24 || key.length == 32;
}
Ответы
Ответ 1
Все правильно. AES обрабатывает данные блоками. В режиме CBC для расшифровки одного блока используется 2 блока шифротекста. Выглядит это приблизительно так: расшифрованый_блок = aes_decrypt(зашифрованый_блок) xor (предыдущий_зашифр_блок) По-этому ошибка в 1 байте шифротекста приведет к неправильной расшифровке только одного блока. Плюс один байт в другом блоке (из-за операции xor). Если вам нужно, что бы ломались все блоки после ошибки, можете использовать другой режим шифрования, например PCBC обладает таким свойством.
Комментариев нет:
Отправить комментарий