cipher.doFinal дополнительные байты

Я пытаюсь зашифровать изображение в Android. Я преобразовал изображение в байтовый массив. Позже я хочу использовать зашифрованный текст для создания нового растрового изображения и его сохранения. Код ниже для моего шифрования

private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static int KEY_LENGTH = 256;
...
public static byte[][] encrypt(byte[] plaintext, SecretKey key, byte[] salt) {
    try {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

        byte[] iv = generateIv(cipher.getBlockSize());
        IvParameterSpec ivParams = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
        byte[] cipherText = cipher.doFinal(plaintext);

        return new byte[][]{salt, iv, cipherText};

    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

Проблема состоит в том, что cipherText имеет дополнительные 16 байтов, когда функция возвращается.

Например, открытый текст имеет размер 7680000 байт, а cipherText имеет 7680016 байт. Изображение имеет размер 1600x1200, поэтому 1600x1200x4= 7680000. Я не могу сохранить 7680016 байт в качестве изображения:(Что это за дополнительные 16 байт? Я что-то не так делаю?

2 ответа

Решение

Я думаю, вы не должны беспокоиться о размере файла. Когда я выполнил аналогичную задачу, у меня было дополнительно 10 байтов в одном конкретном растровом изображении.

Но если вы хотите открыть зашифрованное изображение, чтобы его можно было открыть, то вы должны заменить первые 54 байта файла растрового изображения исходным изображением. (заголовок 54 байта bmp дает информацию о растровом изображении)

Я зашифровал этот файл изображения с помощью инструмента openssl. Вот как я выбрал первые 54 байта и заменил их зашифрованным растровым файлом.

Если вы хотите сделать что-то подобное. Убедитесь, что после расшифровки вы также должны изменить 54 байта из исходного заголовка.

Дополнительные 16 байтов почти наверняка связаны с заполнением. Заполнение делает шифрование несколько более безопасным, но если вы не возражаете против этого, вы можете изменить третий компонент имени шифра ((который представляет алгоритм заполнения) на NoPaddingШифровать имя "AES/CBC/NoPadding",

Вы можете найти все подробности о том, как имена криптографических алгоритмов работают в документации по архитектуре безопасности Java.

В целом, однако, вы не должны полагаться на размер вывода, генерируемого шифром - шифры тщательно спроектированы так, чтобы быть максимально безопасными, и вы должны оставить размер вывода на них.

Другие вопросы по тегам