4

我已经为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 时才会引发异常。这似乎引发了提到的异常。
4

1 回答 1

4

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

Blowfish 是一种64 位块大小的算法,因此两者作为“开箱即用”的认证加密组合不兼容。对于3DES. 例外不是 Crypto++ 中的错误。

GCM 将与其他具有 128 位块大小的 Crypto++ 对象一起使用。它们包括AESCast-256Rijndael CameillaMARS和。Applied Crypto++: Block Ciphers提供了块大小表。SerpentTwofish

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

Crypto++BlockSize()有时会返回 0(它与模板参数有关)。相反,请使用编译时常量,如AES::BLOCKSIZE,Camellia::BLOCKSIZERijndael::BLOCKSIZE. 这可以被认为是一个错误。

于 2014-01-09T07:57:45.213 回答