Я пытаюсь реализовать чистое, правильное и безопасное шифрование 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, поэтому они были идентичны. Спасибо за помощь!