АЕС. javax.crypto.Cipher возвращает пустой массив в режиме расшифровки

Я сам реализую режим CBC. И я использую AES в качестве функции E для каждого блока CBC.

Вот мой код шифрования:

public static List<Byte> encrypt(List<Byte> bytes, byte[] key) throws Exception {
    byte[] bytesArray = BytesConverter.toByteArray(bytes);

    SecretKey secretKey = new SecretKeySpec(key, AES);

    Cipher cipher = Cipher.getInstance(AES);
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    return BytesConverter.toByteList(cipher.update(bytesArray));
}

Я использую update, потому что не хочу добавлять панель AES. Я делаю это сам для последнего блока в начале алгоритма CBC.

Когда я хочу расшифровать блок зашифрованного текста, я использую ту же функцию с Cipher.DECRYPTION_MODE.

public static List<Byte> decrypt(List<Byte> bytes, byte[] key) throws Exception {
    byte[] bytesArray = BytesConverter.toByteArray(bytes);

    SecretKey secretKey = new SecretKeySpec(key, AES);

    Cipher cipher = Cipher.getInstance(AES);
    cipher.init(Cipher.DECRYPT_MODE, secretKey);

    return BytesConverter.toByteList(cipher.update(bytesArray));
}

Проблема в том, что Cipher.update в режиме расшифровки возвращает пустой массив байтов для ввода, который был зашифрован методом encrypt.

Я в замешательстве. Что не так?


person Anton Holovin    schedule 05.10.2014    source источник
comment
Обратите внимание, что List<Byte> будет потреблять примерно в 16 раз больше памяти, чем байтовый массив из-за упаковки.   -  person SLaks    schedule 05.10.2014
comment
@SLaks, это зависит от реализации BytesConverter.toByteList, но я предполагаю, что используется либо LinkedList, либо ArrayList, и вы, безусловно, правы в этих случаях. И практически нет причин использовать List. Посмотрите на java.nio.ByteBuffer, если вам нужна оболочка.   -  person Maarten Bodewes    schedule 06.10.2014
comment
@owlstead Мне просто нужен подсписок. Вот почему я использую список.   -  person Anton Holovin    schedule 06.10.2014
comment
И я использую ByteBuffer.slice. Или просто Arrays.copyOfRange конечно, если подсписок небольшой. ДОПОЛНИТЕЛЬНО Обратите внимание, что вы также можете просто указать смещение и длину в вызовах обновления, нет прямой необходимости работать вне массива байтов, если вы не хотите использовать ByteBuffer. Обратите внимание, что обработка position и limit в ByteBuffer требует некоторого привыкания, внимательно прочитайте API, если вы идете по этому пути.   -  person Maarten Bodewes    schedule 06.10.2014


Ответы (1)


Вы пропустили вызов doFinal. Из-за заполнения для шифрования режима ECB и CBC экземпляры Cipher требуются для буферизации до размера блока - 1 байт, который будет только дополнен и зашифрован (или расшифрован и не дополнен) в вызове doFinal(), который освобождает последнюю часть зашифрованный текст (или открытый текст для расшифровки).

Что вам следует сделать, так это использовать "AES/ECB/NoPadding" и только doFinal вместо update для реализации CBC для каждого блока (хотя может работать только update, но это не указано на 100%). Это идентично блочному шифрованию базового шифра AES. Вы также можете использовать упрощенный (то есть прямой, не-JCE) API Bouncy Castle более низкого уровня, который предоставляет механизмы AES, которые просто реализуют сам блочный шифр.

person Maarten Bodewes    schedule 05.10.2014
comment
Но если я попытаюсь зашифровать полный 16-байтовый блок, он добавит еще один фиктивный блок для следующего unpadd, верно? Таким образом, на выходе будет 32 байта (16 зашифрованных байтов + 16 фиктивных байтов). Это не то, чего я хочу. - person Anton Holovin; 06.10.2014
comment
Вы можете использовать CTR, но обратите внимание, что если вы когда-нибудь повторно используете IV, вы, вероятно, потеряете всю конфиденциальность. Если вы хотите иметь зашифрованный текст того же размера без определения IV, вы переходите к части криптографии, называемой шифрованием с сохранением формата. Также обратите внимание, что вам обычно нужен тег аутентификации, например. с помощью шифрования в режиме GCM, которое также занимает несколько байтов. - person Maarten Bodewes; 06.10.2014
comment
Вышеприведенный общий совет, я обновил ответ, чтобы указать, как обращаться с режимом CBC. - person Maarten Bodewes; 06.10.2014
comment
Спасибо. Не догадался, что "AES/ECB/NoPadding" это то, что мне нужно. - person Anton Holovin; 06.10.2014