加密++对称算法和经过身份验证的块模式组合



我已经为Crypto++v5.6.2实现了一个C++包装器库,并且对对称算法(例如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时才会引发异常。这似乎提出了所提到的例外情况

GCM被设计为仅适用于128位(=16字节)的块大小。你可以在第5.1节的原始论文中找到这一点。

Blowfish是一种64位块大小算法,因此两者作为"开箱即用"的身份验证加密组合是不兼容的。3DES也是如此。该异常不是Crypto++中的错误。

GCM将与其他具有128位块大小的Crypto++对象一起工作。它们包括AESCast-256RijndaelCameillaMARSSerpentTwofish。块大小表可在Applied Crypto++:块密码中获得。

GCM也不适用于较大的块大小。例如,Rijndael(AES的父级)提供192位和256位块大小(AES仅指定128位块大小)。GCM不适用于较大的块大小。对于具有256位块大小的SHACAL-2也是如此。

Crypto++的BlockSize()有时会返回0(这与模板参数有关)。相反,使用AES::BLOCKSIZECamellia::BLOCKSIZERijndael::BLOCKSIZE等编译时常数。这可能被认为是一个错误。

最新更新