我使用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"/>
我想知道是否存在Charset问题,并且存在一种从十六进制读取加密文件以避免此类问题的方法。
答案 0 :(得分:2)
这不是加密,加密只适用于8位字节,广告没有它们的概念。
填充只会在数据末尾添加字节,并且只能影响最后16个字节,所以它不是填充问题。
字符串编码可能有所不同,要加密的字符串会根据编码转换为字节,解密后,字节会通过sone编码重新编码为字符串。
答案 1 :(得分:1)
这看起来不对:
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不会欺骗机器。
可能类似于Crypto ++ wiki上的CBC Mode中的以下内容:
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 mode,CCM mode和GCM mode。另请参阅Crypto ++ wiki上的Authenticated Encryption。