Java cipher.doFinal () записывает дополнительные байты - PullRequest
8 голосов
/ 04 августа 2009

Я реализую шифрование / дешифрование с использованием Java Cipher и AES. Все работает хорошо, за исключением того, что при вызове doFinal () написано 5 дополнительных байтов. Итак, я получаю правильно декодированную строку с добавлением 5 дополнительных байтов.

Я считаю, что причина в том, что пишется весь блок из 16 байтов. Я вижу 3 16-байтовых блока, включая последний. Входной зашифрованный файл составляет 64 байта. Размер незашифрованного текста должен составлять 43 байта.

Документация для doFinal указывает, что он может вернуть количество байтов, записанных в выходной буфер. Тем не менее, это 0,16,16,16. Я попробовал все формы doFinal и обновления и не получил никаких изменений в поведении.

В некотором смысле имеет смысл написать полный блок, поскольку именно так работает большинство этих алгоритмов. Однако, если он не скажет мне размер выходных данных, как я должен предотвратить избыточные данные?

Должен ли я использовать другой алгоритм? AES256 является требованием, но мне интересно, может ли другой тип блока или тип заполнения позволить ему написать правильное количество байтов.

Любое руководство?

Использовано для краткости:

decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey);

Деловая часть процедуры расшифровки.

    long bytesToRead = inputFile.length();

    while ((inLen = in.read(buffer)) > 0) {
        int bytesOut = 0;
        byte[] cryptBytes = null;
        int outLen = cipher.getOutputSize(inLen);
        cryptBytes = new byte[outLen];

        if (bytesToRead <= buffer.length) {
            try {
                bytesOut = cipher.doFinal(buffer, 0, inLen, cryptBytes, 0);
            } catch (ShortBufferException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else
            try {
                bytesOut = cipher.update(buffer, 0, inLen, cryptBytes, 0);
            } catch (ShortBufferException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        out.write(cryptBytes, 0, bytesOut);
        bytesToRead -= inLen;

    }
    try {
        out.flush();
        in.close();
        out.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Ответы [ 2 ]

15 голосов
/ 04 августа 2009

Вы должны указать механизм заполнения при вызове Cipher.getInstance () - очевидно, он должен быть одинаковым как во время шифрования, так и во время дешифрования. например:

decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

Без механизма заполнения сторона дешифрования не имеет информации о том, где находится конец открытого текста (в последнем блоке).

1 голос
/ 04 августа 2009

AES - это блочный шифр , естественно, он даст вам целые блоки, как и все блочные шифры.

См. Статью Википедии об AES для получения дополнительной информации.

Вы сказали, что хотите, чтобы он выводил "правильное количество байтов". Как вы решили, какое число байтов правильное?

...