Расшифровка с помощью Cipher и AES дает 208 расшифрованных байтов, за которыми следует мусор - PullRequest
0 голосов
/ 30 сентября 2010

[Редактировать: не пытайтесь понять все это и не тратьте свое время на чтение всего моего вопроса - просто имейте в виду, что расшифровка дошла до определенной позиции ... и прочитайте мой ответ это объясняет почему!]

У меня возникла досадная проблема, я понятия не имею, как ее решить ...

Система записывает зашифрованные данные в файлы, некоторые являются сериализованными объектами, другие - текстовыми (XML) файлами. Базовый класс, который выполняет расшифровку при необходимости, инициализирует шифр с шифрованием AES, подготавливает ключ (считывается из файла) и имеет способы доступа к данным:

Способ получить InputStream:

public InputStream getInputStream(File pFile) throws IOException {
  return
    new CipherInputStream(
      new BufferedInputStream(new FileInputStream(pFile)),
      getCipher(Cipher.DECRYPT_MODE)
    );
}

и метод для чтения объекта, который просто оборачивает ObjectInputStream вокруг InputStream, полученного из этого метода, и читает объект, используя ObjectInputStream.readObject().

Теперь. В системе программного обеспечения все работает таким образом. Я хотел написать инструмент командной строки, помогающий расшифровать файлы для поддержки. Итак, я использовал точно такие же методы для получения моего шифра, я даже использовал идентичный класс и встроенный там InputStream.

Но: что бы я ни делал: дешифруются только первые 208 (!) Байтов, остальные остаются зашифрованными!

Я пытался просто «скопировать» данные из этого InputStream в новый OutputStream, используя байтовый буфер, но я также попытался просто получить строку из данных, чтобы увидеть, что происходит в отладчике. => Эффект всегда одинаков. До этой «границы» в 208 байт я вижу чистый текст, за которым следует мусор.

Понятия не имею, что здесь может пойти не так! Любые подсказки ??

Шифр ​​создается так:

public Cipher getCipher(int opMode) throws IOException {
    Cipher cipher = null;

    try {
        cipher = Cipher.getInstance("AES");
    } catch (NoSuchAlgorithmException e) {
        throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e);
    } catch (NoSuchPaddingException e) {
        throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e);
    }
    try {
        cipher.init(opMode, readKey());
    } catch (InvalidKeyException e) {
        throw new MdmInvalidKeyException();
    } catch (ClassNotFoundException e) {
        throw new MdmInvalidKeyException();
    } catch (NumberFormatException e) {
        throw new MdmInvalidKeyException();
    }
    return cipher;
}

Итак, вот код, который фактически использует InputStream IN в программной системе:

String s = readStream(reader.getInputStream(file));

где readStream реализован так:

public String readStream(InputStream is) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));

    StringBuffer sb = new StringBuffer();
    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line).append('\n');
        }
    } finally {
        reader.close();
    }

    return sb.toString();
}

Все это работает (в программном обеспечении)! Но моя попытка прочитать его таким же образом не удалась: строка содержит ровно 208 расшифрованных символов, за которыми следует мусор !!

Написание XML-файлов выполняется с точностью до наоборот, но здесь это действительно не имеет значения, потому что показанный код работает внутри системы, а не в моей простой программе копирования! Я использую там точно такой же класс! Зачем вообще расшифровывать всего 208 символов ??

Спасибо!

Редактировать: Теперь ясно, что эффект расшифровки только определенного количества байтов зависит от ОС и машины! В моей ОС Windows с 32-битным Java 1.6 Update 20 не удается расшифровать - на компьютере с Linux с 64-битным Java 1.6 Update 18 это работает !!

Итак, вот проблема: кто-нибудь знает, как это влияет на вывод ??? 1042 *

Ответы [ 2 ]

1 голос
/ 02 ноября 2010

AES - это блочный шифр, поэтому он должен шифровать блоки точного размера (16 байт).Когда вы шифруете данные, вы должны убедиться, что они могут быть разбиты на блоки по 16 байт;если последний блок короче этого, вы можете получить исключение или мусор (из-за способа работы Buffered Streams).Если вы не хотите возиться с ручным заполнением ваших данных, тогда вы можете настроить шифр для использования PKCS5Padding.Вместо того, чтобы просто вызывать Cipher.getInstance ("AES"), вы должны использовать Cipher.getInstance ("AES / ECB / PKCS5Padding"), и вы должны сделать это по ОБА сторонам.

Также я рекомендую использоватьCBC или CFB, вам нужен вектор инициализации (соль) для этих режимов, но это лучше, чем использование ECB, которое аналогично использованию без режима, это означает, что вы просто шифруете каждый блок независимо, поэтому любой блок может быть взломан отдельно.Если вы используете CBC или CFB, то для взлома блока данных вам нужно взломать предыдущий блок (CBC означает Cipher Block Chaining).

И последнее, но не менее важное ... если вы хотите зашифровать данные поверхпоток, вам может быть лучше использовать потоковый шифр, такой как RC4, вместо блочного шифра.

0 голосов
/ 03 марта 2011

Это немного неловко - но я оставляю здесь этот (отвеченный!) Вопрос на случай, если кто-нибудь когда-нибудь столкнется с подобной проблемой!

Причина, по которой я правильно расшифровал хх байт, а затем мусор, легко объяснима - позор мне!

У нас были файлы XML, зашифрованные в системе Linux. Расшифровка внутри самой системы работала нормально; но всякий раз, когда я пытался расшифровать их на своем компьютере с Windows, он терпел неудачу, как описано.

ПОЧЕМУ? Поскольку расширения файлов являются XML - и мой инструмент WinScp FTP обрабатывает файл с расширением XML как текстовые файлы - И заменяет каждый LF (# 10) на CR LF (# 13 # 10)!

Таким образом, расшифровка работала правильно, пока не был поражен первый глупый символ CR! : - (

Итак, мы учимся: никогда не задавайте двоичному файлу расширение текстового файла, если не хотите неприятностей! * Вздох *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...