Симметричные алгоритмы Crypto++ и аутентифицированные комбинации режимов блоков

Я реализовал библиотеку оболочки C++ для Crypto ++ v5.6.2 и у меня возник вопрос о комбинациях симметричных алгоритмов (например, Blowfish) и блочных режимов (например, GCM).

Я могу зашифровать и расшифровать данные с помощью Blowfish/EAX, но не могу добиться того же с помощью Blowfish/GCM. AES/EAX и AES/GCM оба работают.

Следующее простое приложение демонстрирует мою проблему:

#include <iostream>
#include <string>

#include "cryptopp/blowfish.h"
#include "cryptopp/filters.h"
#include "cryptopp/eax.h"
#include "cryptopp/gcm.h"
#include "cryptopp/osrng.h"
#include "cryptopp/hex.h"

std::string encrypt(
    CryptoPP::AuthenticatedSymmetricCipher &encryption,
    std::string const kPlainText,
    CryptoPP::SecByteBlock const kKey,
    unsigned const char * kIV) {
  std::string cipher_text;

  // TODO Is this the source of the problem?
  // BlockSize always returns 0 which leads to an exception if GCM block mode is used!
  std::cout << encryption.BlockSize() << " bytes" << std::endl;

  encryption.SetKeyWithIV(
      kKey,
      kKey.size(),
      kIV
  );

  CryptoPP::StringSink *string_sink = new CryptoPP::StringSink(cipher_text);
  CryptoPP::BufferedTransformation *transformator = NULL;

  // The AuthenticatedEncryptionFilter adds padding as required.
  transformator = new CryptoPP::AuthenticatedEncryptionFilter(
      encryption,
      string_sink);

  bool const kPumpAll = true;
  CryptoPP::StringSource(
      kPlainText,
      kPumpAll,
      transformator);

  return cipher_text;
}

std::string decrypt(
    CryptoPP::AuthenticatedSymmetricCipher &decryption,
    std::string const kCipherText,
    CryptoPP::SecByteBlock const kKey,
    unsigned const char * kIV) {
  std::string recovered_plain_text;

  decryption.SetKeyWithIV(
      kKey,
      kKey.size(),
      kIV);

  CryptoPP::StringSink *string_sink = new CryptoPP::StringSink(
      recovered_plain_text);
  CryptoPP::BufferedTransformation *transformator = NULL;
  CryptoPP::AuthenticatedDecryptionFilter *decryption_filter = NULL;

  decryption_filter = new CryptoPP::AuthenticatedDecryptionFilter(
      decryption,
      string_sink);
  transformator = new CryptoPP::Redirector(*decryption_filter);

  bool const kPumpAll = true;
  CryptoPP::StringSource(
      kCipherText,
      kPumpAll,
      transformator);

  return recovered_plain_text;
}

int main() {
  CryptoPP::AutoSeededRandomPool prng;
  CryptoPP::SecByteBlock key(CryptoPP::Blowfish::DEFAULT_KEYLENGTH);
  prng.GenerateBlock(key, key.size());

  byte iv[CryptoPP::Blowfish::BLOCKSIZE];
  prng.GenerateBlock(iv, sizeof(iv));

  // Creates templated mode objects of  block ciphers.

  // This works...
//  CryptoPP::EAX<CryptoPP::Blowfish>::Encryption encryption;
//  CryptoPP::EAX<CryptoPP::Blowfish>::Decryption decryption;

  // This does NOT work...
  CryptoPP::GCM<CryptoPP::Blowfish>::Encryption encryption;
  CryptoPP::GCM<CryptoPP::Blowfish>::Decryption decryption;

  std::string plain_text = "Block Mode Test";
  std::string cipher_text = encrypt(encryption, plain_text, key, iv);
  // terminate called after throwing an instance of 'CryptoPP::InvalidArgument'
  // what():  Blowfish/GCM: block size of underlying block cipher is not 16

  std::cout << "cipher text: " << std::hex << cipher_text << std::endl;
  std::cout << "recovered plain text: " << decrypt(decryption, cipher_text, key, iv) << std::endl;
}

CryptoPP::InvalidArgument Исключение выдается, если запустить приведенный выше код со следующим текстом:

Blowfish/GCM: block size of underlying block cipher is not 16

Но при запуске кода вместо этого в блочном режиме EAX исключение не выдается. Итак, мои вопросы:

  • GCM работает только с AES? Можно ли использовать GCM с Blowfish или 3DES?
  • Доступна ли матрица, в которой перечислены все возможные комбинации симметричных алгоритмов с блочными режимами?
  • Или это ошибка в Crypto++? Потому что метод BlockSize() всегда возвращается 0 но исключение возникает только при использовании Blowfish (или 3DES) вместо AES. Это поднимает упомянутое исключение.

1 ответ

GCM был разработан для работы только с размером блока 128 бит (=16 байт). Вы можете найти это в оригинальной статье в разделе 5.1.

Blowfish - это 64-битный алгоритм с размером блока, поэтому они не совместимы как комбинация аутентифицированного шифрования "из коробки". То же самое верно для 3DES, Исключением не является ошибка в Crypto++.

GCM будет работать с другими объектами Crypto++, которые имеют 128-битный размер блока. Они включают AES, Cast-256, RijndaelCameilla, MARS, Serpent а также Twofish, Таблица размеров блоков доступна в Applied Crypto++: Блочные шифры.

GCM также не будет работать с блоками большего размера. Например, Rijndael (родитель AES) предлагает 192-битный и 256-битный размеры блоков (AES указывает только 128-битный размер блока). GCM не будет работать с блоками большего размера. И то же самое верно для SHACAL-2, с 256-битным размером блока.

Crypto++ s BlockSize() иногда возвращает 0 (это связано с параметрами шаблона). Вместо этого используйте константы времени компиляции, такие как AES::BLOCKSIZE, Camellia::BLOCKSIZE а также Rijndael::BLOCKSIZE, Это можно считать ошибкой.

Другие вопросы по тегам