Расшифрованный файл имеет странные символы после процесса расшифровки AES CBC
Я расшифровываю файл методом AES CBC, используя библиотеку Cryptopp в библиотеках vC++, VS2015 и QT. Я мог получить расшифрованный файл результатов, но есть некоторые символы, которые расшифровываются неправильно.
Код, который я использую:
const std::string encrypted_file("C:\\TEMP\\G0030013.xml");
const std::string decrypted_file("C:\\TEMP\\decrypted0.xml");
const int key_size(CryptoPP::AES::DEFAULT_KEYLENGTH);
const int iv_size(CryptoPP::AES::BLOCKSIZE);
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryption;
CryptoPP::StreamTransformationFilter *decryptor =
new CryptoPP::StreamTransformationFilter(decryption,
new CryptoPP::FileSink(decrypted_file.c_str()),
CryptoPP::StreamTransformationFilter::BlockPaddingScheme::ZEROS_PADDING);
decryption.SetKeyWithIV(key, key_size, iv, iv_size);
CryptoPP::FileSource file_source(encrypted_file.c_str(), true, decryptor);
Результирующий xml:
<BG Val="149" Dt="2014-01-14" Tm="15:37" D="1"/>
<BG Val="158" Dt="2014-01-14" Tm="15:39" Flg="M3" D="í/ˉOæÚ…f÷ûâÄò" Dt="2014-01-14" Tm="16:00" D="1"/>
<BG Val="56" Dt="2014-01-14" Tm="16:01" D="1"/>
<BG Val="60" Dt="2014-01-14" Tm="16:12" D="1"/>
<BG Val="58" Dt="2014-01-14" Tm="16:13" D="1"/>
<BG Val="56" Dt="2014-01-14" Tm="16:16" Flg="M3" D="1"/>
<BG Val="155" Dt="2014-01-14" Tm="16:32" D="1"/>
<BG Val="168" Dt="2014-01-14" Tm="16:33" D="1"/>
<BG Val="155" Dt="2015-06-29" Tm="17:52" Flg="M3" D="1"/>
<BG Val="138" Dt="2015-07-03" Tm="09:00" Flg="M1" D="1"/>
<BG Val="141" Dt="2015-07-03" Tm="18:24" D="ðÂwÝfIïs¯¤eåˆöm5" Dt="2015-07-06" Tm="08:28" Flg="M1" D="1"/>
<BG Val="147" Dt="2013-10-18" Tm="08:40" Ctrl="?" D="1"/>
<BG Val="142" Dt="2015-11-19" Tm="10:57" Ctrl="?" D="1"/>
Когда это должно быть:
<BG Val="149" Dt="2014-01-14" Tm="15:37" D="1"/>
<BG Val="158" Dt="2014-01-14" Tm="15:39" Flg="M3" D="1"/>
<BG Val="57" Dt="2014-01-14" Tm="16:00" D="1"/>
<BG Val="56" Dt="2014-01-14" Tm="16:01" D="1"/>
<BG Val="60" Dt="2014-01-14" Tm="16:12" D="1"/>
<BG Val="58" Dt="2014-01-14" Tm="16:13" D="1"/>
<BG Val="56" Dt="2014-01-14" Tm="16:16" Flg="M3" D="1"/>
<BG Val="155" Dt="2014-01-14" Tm="16:32" D="1"/>
<BG Val="168" Dt="2014-01-14" Tm="16:33" D="1"/>
<BG Val="155" Dt="2015-06-29" Tm="17:52" Flg="M3" D="1"/>
<BG Val="138" Dt="2015-07-03" Tm="09:00" Flg="M1" D="1"/>
<BG Val="141" Dt="2015-07-03" Tm="18:24" D="1"/>
<BG Val="135" Dt="2015-07-06" Tm="08:28" Flg="M1" D="1"/>
<BG Val="147" Dt="2013-10-18" Tm="08:40" Ctrl="?" D="1"/>
<BG Val="142" Dt="2015-11-19" Tm="10:57" Ctrl="?" D="1"/>
Мне интересно, если есть проблема с Charset и существует ли способ чтения зашифрованного файла из шестнадцатеричного числа, чтобы избежать такого рода проблем.
2 ответа
Это не шифрование, шифрование работает только на 8-битных байтах, и у них нет понятия, что это такое.
Заполнение добавляет только байты к концу данных и может влиять только на последние 16 байтов, поэтому это не проблема заполнения.
Это может быть различие в кодировании строки, строка, которая должна быть зашифрована, преобразуется в байты на основе кодирования, и после дешифрования байты повторно кодируются в строку с кодированием sone.
Это выглядит не так:
const int key_size(CryptoPP::AES::DEFAULT_KEYLENGTH);
const int iv_size(CryptoPP::AES::BLOCKSIZE);
Я не думаю, что это незаконно, это просто необычно. Я думаю, что вы получаете 1 int инициализированный к значению (либо AES::DEFAULT_KEYLENGTH
или же AES::BLOCKSIZE
).
Обычно вы делаете что-то вроде:
// Memory is allocated
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
SecByteBlock iv(AES::BLOCKSIZE);
// Set them to 0
memset(key, 0x00, key.size());
memset(iv, 0x00, iv.size());
Тогда, если вы только скопируете 14 байтов в key
два хвостовых байта будут в известном состоянии.
Исходя из вышеизложенного, я предполагаю, что вы используете какой-то мусор для ключей.
... CryptoPP:: FileSource file_source (encrypted_file.c_str (),...
В общем, вы должны быть осторожны с использованием c_str()
потому что неизвестно, когда встроенный NULL может отображаться в простом тексте или зашифрованном тексте. Вы должны быть в порядке с кодом выше при использовании его в качестве имени файла. Но вот простой текст со встроенным NULL:
std::string plain("asdfg\0hjkl", 10);
Лучше использовать перегрузку источника, фильтров и приемников, которые принимают (1) byte*
(данные) и size_t
(Длина); или (2) std::string
(не C-строка). (2) использует string::data
а также string::length
поэтому встроенные значения NULL не обманывают механизм.
Может быть, что-то вроде следующего из CBC Mode в вики Crypto++:
CBC_Mode< AES >::Encryption e;
e.SetKeyWithIV( key, key.size(), iv );
// The StreamTransformationFilter adds padding
// as required. ECB and CBC Mode must be padded
// to the block size of the cipher.
StringSource ss( plain, true,
new StreamTransformationFilter( e,
new StringSink( cipher )
) // StreamTransformationFilter
); // StringSource
А также:
CBC_Mode< AES >::Decryption d;
d.SetKeyWithIV( key, key.size(), iv );
// The StreamTransformationFilter removes
// padding as required.
StringSource ss( cipher, true,
new StreamTransformationFilter( d,
new StringSink( recovered )
) // StreamTransformationFilter
); // StringSource
Вместо StringSink
Вы можете просто использовать FileSink
:
... new FileSink(decrypted_file.c_str())
Режим CBC обеспечивает только конфиденциальность и не обнаруживает взлома. Обычно вы также хотите обнаружить взлом. Для этого проверьте режим EAX, режим CCM и режим GCM. Также см. Раздел Аутентифицированное шифрование в вики Crypto++.