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

时间:2014-01-07 09:25:56

标签: c++ encryption encryption-symmetric crypto++ block-cipher

我为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时才会引发异常。这似乎引起了上述例外。

1 个答案:

答案 0 :(得分:4)

GCM仅适用于 128位(= 16字节)块大小。您可以在第5.1节的original paper中找到它。

Blowfish是 64位块大小算法,因此这两者不兼容作为“开箱即用”的经过身份验证的加密组合。 3DES也是如此。例外不是Crypto ++中的错误。

GCM将与其他具有128位块大小的Crypto ++对象一起使用。它们包括AESCast-256Rijndael CameillaMARSSerpentTwofish。可以在Applied Crypto++: Block Ciphers处找到块大小的表格。

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

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