Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Почему AES расшифровывается именно таким образом?

#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 обладает таким свойством.

Комментариев нет:

Отправить комментарий