解密的文件在AES CBC解密过程后具有奇怪的字符



我正在使用 vc++、VS2015 和 QT 库中的 Cryptopp 库使用 AES CBC 方法解密文件。我可以获得解密的结果文件,但有些字符未正确解密。

我使用的代码是:

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"/>

我想知道是否存在字符集问题,并且存在一种从十六进制读取加密文件以避免此类问题的方法。

这不是加密,加密只适用于 8 位字节,广告没有它们是什么的概念。

填充只会在数据末尾添加字节,并且只能影响最后 16 个字节,因此这不是填充问题。

这可能是字符串编码

的差异,要加密的字符串根据编码转换为字节,解密后,字节被重新编码为带有 sone 编码的字符串。

看起来不对:

const int key_size(CryptoPP::AES::DEFAULT_KEYLENGTH);
const int iv_size(CryptoPP::AES::BLOCKSIZE);

我不认为这是非法的,它只是不寻常。我认为您将 1 个 int 初始化为值(AES::DEFAULT_KEYLENGTHAES::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("asdfghjkl", 10); 

更好的是,使用源、滤波器和接收器的重载,它们采用 (1) byte*(数据)和size_t(长度)或 (2) std::string(不是 C 字符串)。(2) 使用string::datastring::length,因此嵌入式 NULL 不会欺骗机器。

也许类似于Crypto++维基上的CBC模式:

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++ wiki 上的经过身份验证的加密。

最新更新