当您已经拥有用于密码分析的密文时,在 CBC 模式下解密密文字符串的更好方法
您使用的是 CTS 模式,而不是 CBC 模式。所以第一步是使用正确的模式;)
这是来自 Crypto++ wiki CBC Mode的 CBC 加密和解密示例:
AutoSeededRandomPool prng;
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
prng.GenerateBlock( key, key.size() );
byte iv[ AES::BLOCKSIZE ];
prng.GenerateBlock( iv, sizeof(iv) );
string plain = "CBC Mode Test";
string cipher, encoded, recovered;
/*********************************\
\*********************************/
try
{
cout << "plain text: " << plain << endl;
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
}
catch( const CryptoPP::Exception& e )
{
cerr << e.what() << endl;
exit(1);
}
/*********************************\
\*********************************/
// Pretty print cipher text
StringSource ss( cipher, true,
new HexEncoder(
new StringSink( encoded )
) // HexEncoder
); // StringSource
cout << "cipher text: " << encoded << endl;
/*********************************\
\*********************************/
try
{
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
cout << "recovered text: " << recovered << endl;
}
catch( const CryptoPP::Exception& e )
{
cerr << e.what() << endl;
exit(1);
}
这是一个典型的输出:
$ ./driver.exe
key: B00DDF9D93E199EFEAE967805E0A5228
iv: CA8A8878F145C9B9B3C31A1F15C34A6D
plain text: CBC Mode Test
cipher text: D6AF39534926C21CFF3E7477A7146FF3
recovered text: CBC Mode Test
字符串密文 = "C7A4123420BF4EFFB815BC0EA8B46D00F440D068CDD9BB28860DC3E9B312710743"
您可能想要做的第二件事是将字符串从十六进制编码更改为二进制。这在HexDecoder下的 Crypto++ wiki 中有介绍:
string encoded = "FFEEDDCCBBAA99887766554433221100";
string decoded;
StringSource ss(encoded,
new HexDecoder(
new StringSink(decoded)
) // HexDecoder
); // StringSource
上面的代码运行后,你会得到一个可能嵌入了NULL
s 的二进制字符串。所以一定要使用decoded.data()
指针,以及decoded.size()
二进制字符串的长度。
当解密输出时,我得到各种符号、数字、字母和疯狂。
这可能意味着解密失败。真正判断的唯一方法是您是否在密文上提供了像 HMAC 这样的身份验证标签。否则,您将得到这些结果。
如果您使用需要填充的模式(如 CBC 模式),那么当填充恰好正确时,您仍然会得到虚假命中。唯一明确的方式是提供身份验证标签。
我构建了一个函数来生成密钥未知和已知部分的所有可能组合和排列。
您也应该显示该例程,以防它出现错误。我们无法评论您排列位的方式,但我们可以评论它是否看起来像 Crypto++ 使用的那样生成二进制字符串。
我打算手动解密消息和 CBC 的 XOR,但我没有时间。
我真的不知道该怎么做......你想在ECB模式下操作AES然后自己执行XOR吗?如果是这样,您可能会考虑使用ArrayXorSink。