2014-10-05 5 views
0

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

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

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 algorythm.

Когда я хочу расшифровать блок cyphertext, я использую ту же функцию с 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.

Я смущен. Что не так?

+1

Обратите внимание, что 'List ' будет потреблять примерно в 16 раз больше памяти, чем массив байтов из-за бокса. – SLaks

+1

@SLaks, который зависит от реализации 'BytesConverter.toByteList', но я полагаю, что используются либо LinkedList, либо ArrayList, и вы наверняка были бы правы в этих случаях. И нет никакого смысла использовать «Список». Посмотрите на 'java.nio.ByteBuffer', если вам нужна оболочка. –

+0

@owlstead Мне просто нужен подсписок. Вот почему я использую List. –

ответ

2

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

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

+0

Но если я попытаюсь зашифровать полный 16-байтовый блок, он добавит еще один фиктивный блок для следующего unpadd, не так ли? Таким образом, вывод будет 32 байта (16 зашифрованных байтов + 16 фиктивных байтов). Я этого не хочу. –

+1

Вы можете использовать CTR, но обратите внимание, что если вы когда-либо повторно используете IV, вы, вероятно, потеряете всю конфиденциальность. Если вы хотите иметь зашифрованный текст такого же размера, не определяя IV, вы переходите в часть криптограммы, называемую «форматом, сохраняющим шифрование». Также обратите внимание, что вам обычно нужен тег аутентификации, например. используя шифрование режима GCM, которое также занимает несколько байтов. –

+1

Вышеупомянутый общий совет, я обновил ответ, чтобы указать, как обращаться с режимом CBC. –