我为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运行代码时,不会抛出任何异常。所以我的问题是:
BlockSize()
始终返回0
,但只有在使用Blowfish(或3DES)而非AES时才会引发异常。这似乎引起了上述例外。答案 0 :(得分:4)
GCM仅适用于 128位(= 16字节)块大小。您可以在第5.1节的original paper中找到它。
Blowfish是 64位块大小算法,因此这两者不兼容作为“开箱即用”的经过身份验证的加密组合。 3DES
也是如此。例外不是Crypto ++中的错误。
GCM将与其他具有128位块大小的Crypto ++对象一起使用。它们包括AES
,Cast-256
,Rijndael
Cameilla
,MARS
,Serpent
和Twofish
。可以在Applied Crypto++: Block Ciphers处找到块大小的表格。
GCM也不适用于较大的块大小。例如,Rijndael
(AES
的父级)提供192位和256位块大小(AES
仅指定128位块大小)。 GCM不适用于较大的块大小。 SHACAL-2
也是如此,块大小为256位。
Crypto ++的BlockSize()
有时会返回0(它与模板参数有关)。相反,使用编译时常量,如AES::BLOCKSIZE
,Camellia::BLOCKSIZE
和Rijndael::BLOCKSIZE
。这可能被视为一个错误。