GCM中的Crypto ++ AES正在产生相似的密文

时间:2018-11-13 21:05:44

标签: c++ cryptography c++17 crypto++

我正在尝试实施正确,安全的准系统,从头到尾的AES加密。出于我的目的,我只想生成某些基准测试程序输出的密文,以模拟将要写成什么样的密文,例如云存储服务器。在阅读了一些内容之后,我得出的结论是,出于我的目的,AES在GCM模式下产生的经过身份验证的加密代表了我将在真实服务器上使用的密文的代表。

从Crypto ++ Wiki页面上的示例代码开始,我想到了以下代码片段,以从文件中读取一些字符串并转储密文。问题是我得到的密文非常相似,上半部分在许多输出中是相同的。我怀疑这是由于我使用/初始化AutoSeededRandomPool的方式引起的,但是我对其了解不足,无法找到解决方法。看起来底层代码正在调用操作系统(Ubuntu 16.04)来生成熵,这使我相信也许两次调用之间没有足够的时间来更改此值。

在此先感谢您提供的帮助。

#include "osrng.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include "cryptlib.h"
#include "hex.h"
#include "filters.h"
#include "aes.h"
#include "gcm.h"
#include "secblock.h"

using namespace std;
using CryptoPP::AutoSeededRandomPool;
using CryptoPP::AutoSeededX917RNG;
using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::AuthenticatedEncryptionFilter;
using CryptoPP::AuthenticatedDecryptionFilter;
using CryptoPP::AES;
using CryptoPP::GCM;
using CryptoPP::SecByteBlock;

// Single randomly seeded RNG
AutoSeededRandomPool rnd;

// Generate a string buffer for the input/output data
string plainText, cipherText, encoded;

// Generate a random key
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
rnd.GenerateBlock(key, key.size());

// Generate an initial value vector (public but unique per msg)
SecByteBlock iv(AES::BLOCKSIZE);
rnd.GenerateBlock(iv, iv.size());

for (size_t i = 0; i < numLines; ++i)
{
    getline(inputFileStream, plainText);

    // Do encryption
    GCM<AES>::Encryption e;
    e.SetKeyWithIV(key, key.size(), iv, iv.size());
    StringSource
    (
        plainText,
        true,
        new AuthenticatedEncryptionFilter
        (
            e,
            new StringSink(cipherText)
        )
    );

    encoded.clear();
    StringSource
    (
        cipherText,
        true,
        new HexEncoder
        (
            new StringSink(encoded)
        )
    );
    cout << "Cipher Text: " << encoded << endl;
}

以下是输出密文的示例:

密文:

  

9DE3A67D5FF42A15834460CD4489B20A352ECEB5F801F7349F3A989DAE8C02675CB48ADDD00604139353F2DEC6335DF8156DA66ACEF953F2E573BB3D88E7AF7D59EE311DC8056CDB0B90B30A232DD7ECB219FB2F9F2D9898B98A1B6749FC8B88D00B5E08DC4EF9C3A52521298D6FBFD75A9A71E8A253D8B9F06D17B07442DA543B8E1CCCEC1E7D7084A1A24DAA71CB688AC2ECD840731F5D57AA7BC61DE5837411596561C36659D95451A003A0E27697528B9BB6B67763F6

密文:

  

9DE3A67D5FF42A15834460CD4489B20A352ECEB5F801F7349F3A989DAE8C02675CB48ADDD00604139353F2DEC6335DF8156DA66ACEF953F2E573BB3D88E7AF7D59EE311DC8056CDB0B90B30A232DD7ECB219FB2F9F2D9898B98A1B6749FC8B88D00B5E08DC4EF9C3A52521298D6FBFD75A9A71E8A253D8B9F06D17B07442DA543B8E1CCCEC1E7D7084A1A24DAA71CB688AC2ECD840731F5D57AA7BC61DE5837411596561C36659D95451A003A0E27697528B9BB6B67763F6D8B9F0691B616C2E996B5E473860EE348C09A1F0FC

将IV生成移出循环,也有类似的行为:

密文:

  

25C638C32E67A7A2C65BF37ABA7C30C19C2714D95FBB68E6E57560CCE2C20F266E6C30768108CF7E01C195991B61AF7FE4F4FA691AFEAAFCFB74292EBE30B9236147722F5785D8F21070D3ACF9E476E39235B4C362D14BF7B2FC2A5BFC0297FCBCBEC37795626029CC30B404A6DB67EA652F5A7FA294D039C4A09BC611F74D8C9FFBD26F49C54470E2C41463440AF050D7FF160CD923FFD0CA6FAF1DB66947C5896B1A39A8E9B694A025E2F521229BDC15C48C5F3AD27A87

密文:

  

25C638C32E67A7A2C65BF37ABA7C30C19C2714D95FBB68E6E57560CCE2C20F266E6C30768108CF7E01C195991B61AF7FE4F4FA691AFEAAFCFB74292EBE30B9236147722F5785D8F21070D3ACF9E476E39235B4C362D14BF7B2FC2A5BFC0297FCBCBEC37795626029CC30B404A6DB67EA652F5A7FA294D039C4A09BC611F74D8C9FFBD26F49C54470E2C41463440AF050D7FF160CD923FFD0CA6FAF1DB66947C5896B1A39A8E9B694A025E2F521229BDC15C48C5F3AD27A87FA3272CFE669E235CE452FCEEA59CC8CA34554FF25

以下答案的附录:

在代码中,我忽略了每次循环迭代时都清除字符串“ cipherText”。显然,StringSink操作只是将新的密文附加到cipherText的末尾,这就是为什么它们相同的原因。感谢您的所有帮助!

1 个答案:

答案 0 :(得分:3)

您正在for循环之外生成密钥和IV。这意味着您将对要加密的行使用相同的密钥/ IV组合。 GCM基本上是带有身份验证标签的CTR加密。这意味着明文中的相似位将产生完全相同的值。只要IV 永不重复,GCM才是安全的。

将IV生成放入循环中,您应该可以。请注意,对于GCM,与16字节IV相比,12字节IV更有效且可能更安全。通常将随机IV放在密文前面(通过手动将其写入StringSink)。

在您的原始代码中,您犯了两个错误。您打印出了密钥而不是IV,这使您认为RNG是错误的。此外,您没有先清除就写入了ciphertext字符串变量。这使得StringSink将下一个密文(和身份验证标签)附加到ciphertext字符串中。因此,在打印出来时,您同时获得了第一和第二个密文。