Перейти к основному содержимому

Вектор инициализации для шифрования

· 8 мин. чтения

1. Обзор

В этом руководстве мы обсудим, как использовать вектор инициализации (IV) с алгоритмами шифрования. Мы также обсудим лучшие практики при использовании IV.

В этой статье предполагается базовое понимание криптографии.

Мы будем использовать алгоритм AES в разных режимах для всех наших примеров.

2. Алгоритмы шифрования

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

Например, алгоритм блочного шифрования обеспечивает безопасность путем шифрования и дешифрования блоков фиксированной длины. Мы используем разные режимы шифрования, чтобы неоднократно применять алгоритм ко всем данным и определять тип используемого IV.

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

3. Вектор инициализации (IV)

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

3.1. Свойства IV

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

Давайте посмотрим на некоторые характеристики IV в зависимости от режима шифрования:

  • Он должен быть неповторяющимся
  • В зависимости от режима шифрования он также должен быть случайным
  • Это не должно быть секретом
  • Это должен быть криптографический одноразовый номер
  • IV AES всегда 128-битный, независимо от длины ключа.

3.2. Генерация IV

Мы можем получить IV непосредственно из класса Cipher :

byte[] iv = cipher.getIV();

Если мы не уверены в реализации по умолчанию, мы всегда можем написать наш метод для генерации IV. Если мы не предоставляем явный IV, то Cipher .getIV() используется для неявного получения IV. Мы можем использовать любой метод для создания IV, если он соответствует описанным выше свойствам.

Во-первых, давайте создадим случайный IV с помощью SecureRandom :

public static IvParameterSpec getIVSecureRandom(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {
SecureRandom random = SecureRandom.getInstanceStrong();
byte[] iv = new byte[Cipher.getInstance(algorithm).getBlockSize()];
random.nextBytes(iv);
return new IvParameterSpec(iv);
}

Далее мы создадим IV, получив параметры от класса Cipher :

public static IvParameterSpec getIVInternal(Cipher cipher) throws InvalidParameterSpecException {
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
return new IvParameterSpec(iv);
}

Мы можем использовать любой из вышеперечисленных методов для создания случайного, непредсказуемого IV. Однако для некоторых режимов, таких как GCM, мы используем IV вместе со счетчиком . В таких случаях мы используем первые несколько байтов, в основном 12 для IV и следующие 4 для счетчика:

public static byte[] getRandomIVWithSize(int size) {
byte[] nonce = new byte[size];
new SecureRandom().nextBytes(nonce);
return nonce;
}

В этом случае нам нужно убедиться, что мы не повторяем счетчик и что IV также уникален.

Наконец, хотя это и не рекомендуется, мы также можем использовать жестко заданный IV .

4. Использование IV в разных режимах

Как мы знаем, основная функция шифрования — маскировать открытый текст, чтобы злоумышленники не могли его угадать. Поэтому мы используем разные режимы шифрования для маскировки шаблонов в зашифрованном тексте.

Такие режимы, как ECB, CBC, OFB, CFB, CTR, CTS и XTS, обеспечивают конфиденциальность. Но эти режимы не защищают от взлома и модификации. Мы можем добавить код аутентификации сообщения (MAC) или цифровую подпись для обнаружения. Мы используем различные реализации, которые обеспечивают комбинированные режимы при шифровании с проверкой подлинности (AE). CCM, GCM, CWC, EAX, IAPM и OCB — вот несколько примеров.

4.1. Режим электронной кодовой книги (ECB)

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

Для шифрования данных в режиме ECB мы используем:

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
ciphertext = cipher.doFinal(data);

Для расшифровки данных в режиме ECB пишем:

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
plaintext = cipher.doFinal(cipherText);

Мы не использовали IV, поэтому один и тот же открытый текст приведет к одному и тому же зашифрованному тексту, что делает его уязвимым для атак. Хотя режим ECB наиболее уязвим, он по-прежнему используется многими провайдерами по умолчанию. Итак, нам нужно быть более бдительными в отношении явной установки режима шифрования.

4.2. Режим цепочки киберблоков (CBC)

В режиме Cyber Block Chaining используется IV, чтобы одинаковые открытые тексты не приводили к одному и тому же зашифрованному тексту. Нам нужно позаботиться о том, чтобы IV был надежно случайным или уникальным. В противном случае мы получим ту же уязвимость, что и ECB Mode .

Давайте получим случайный IV, используя getIVSecureRandom :

IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES");

Во-первых, мы будем использовать IV для шифрования данных в режиме CBC:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);

Далее давайте передадим тот же IV, используя объект IvParameterSpec для расшифровки:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

4.3. Режим Cyber Feedback (CFB)

Режим Cyber Feedback — это самый простой режим потоковой передачи. Это как самосинхронизирующийся поточный шифр. В отличие от режима CBC, здесь нам не нужны никакие отступы. В режиме CFB мы используем IV как источник потока, генерируемого шифром. Опять же, если мы используем один и тот же IV для разных шифровок, сходство может проявиться в зашифрованном тексте. Здесь также, как и в режиме CBC, IV должен быть случайным. В случае предсказуемости IV мы теряем конфиденциальность.

Давайте сгенерируем случайный IV для режима CFB:

IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/CFB/NoPadding");

Другим крайним случаем является то, что если мы используем полностью нулевой IV, то в режиме CFB-8 некоторые ключи могут генерировать полностью нулевой IV и полностью нулевой открытый текст. В этом случае ключи 1/256 не будут генерировать шифрование. Это приведет к возврату открытого текста в виде зашифрованного текста.

Для режимов CBC и CFB повторное использование IV раскрывает информацию об общих блоках, разделяемых двумя сообщениями.

4.4. Режимы счетчика (CTR) и выходной обратной связи (OFB)

Режим счетчика и режим выходной обратной связи превращают блочный шифр в синхронный потоковый шифр. Каждый режим генерирует блоки ключевого потока. В этом случае мы инициализируем шифр конкретным IV. Мы делаем это прежде всего для того, чтобы выделить 12 байт для IV и 4 байта для счетчика. Таким образом, мы можем зашифровать сообщение длиной 2^32 блока.

Здесь давайте создадим IV:

IvParameterSpec ivSpec = CryptoUtils.getIVSecureRandom("AES");

Для режима CTR исходный битовый поток зависит от IV и ключа. Здесь также повторное использование IV приведет к повторному использованию ключевого битового потока. Это, в свою очередь, приведет к нарушению безопасности .

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

4.5. Режим Галуа/Счетчик (GCM)

Режим Galois/Counter — это режим шифрования AEAD. Он сочетает шифрование в режиме счетчика с механизмом аутентификации. Кроме того, он защищает как открытый текст, так и дополнительные аутентифицированные данные (AAD).

Однако эта аутентификация в GCM зависит от уникальности IV. Мы используем одноразовый номер в качестве IV. Если мы повторим хотя бы один IV, то наша реализация может быть уязвима для атак.

Поскольку GCM использует AES для шифрования, IV или счетчик составляют 16 байтов. Поэтому мы используем первые 12 байтов в качестве IV и последние 4 байта nonce в качестве счетчика.

Чтобы создать IV в режиме GCM, нам нужно установить GCMParameterSpec . Давайте создадим IV:

byte[] iv = CryptoUtils.getRandomIVWithSize(12);

Во-первых, давайте получим экземпляр Cipher и инициализируем его с помощью IV:

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv));

Теперь мы создадим и инициализируем Cipher с IV для расшифровки:

cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));

Здесь также нужен уникальный IV, иначе можно расшифровать открытый текст.

4.6. Подведение итогов IV

В следующей таблице приведены типы IV, необходимые для различных режимов:

./4c85b27b0f0585b3f5b4142c221a717c.png

Как мы видели, повторное использование IV с одним и тем же ключом приводит к потере безопасности. Если возможно, мы должны использовать более продвинутые режимы, такие как GCM. Кроме того, некоторые режимы, такие как CCM, недоступны в стандартном дистрибутиве JCE. В этом случае мы можем использовать API-интерфейсы Bouncy Castle для его реализации.

5. Вывод

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

Как всегда, мы можем найти исходный код на GitHub .