Я реализовал библиотеку оболочки 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 исключение не выдается. Итак, мои вопросы:
BlockSize()
всегда возвращается 0
но исключение возникает только при использовании Blowfish (или 3DES) вместо AES. Это поднимает упомянутое исключение.GCM был разработан для работы с 128-битный (= 16 байт) размер блока только. Вы можете найти это в оригинальная бумага в разделе 5.1.
Blowfish является 64-битный размер блока Алгоритм, поэтому эти два не совместимы как «готовая» аутентифицированная комбинация шифрования. То же самое верно для 3DES
, Исключением не является ошибка в Crypto ++.
GCM будет работать с другими объектами Crypto ++, которые имеют 128-битный размер блока. Они включают AES
, Cast-256
, Rijndael
Cameilla
, MARS
, Serpent
а также Twofish
, Таблица размеров блоков доступна по адресу Прикладное Crypto ++: блочные шифры.
GCM также не будет работать с блоками большего размера. Например, Rijndael
(родитель AES
) предлагает 192-битный и 256-битный размеры блоков (AES
указывает только 128-битный размер блока). GCM не будет работать с блоками большего размера. И то же самое верно для SHACAL-2
, с 256-битным размером блока.
Crypto ++ s BlockSize()
иногда возвращает 0 (это связано с параметрами шаблона). Вместо этого используйте константы времени компиляции, такие как AES::BLOCKSIZE
, Camellia::BLOCKSIZE
а также Rijndael::BLOCKSIZE
, Это можно считать ошибкой.
Других решений пока нет …