暗号解読用の暗号文が既にある場合に、CBC モードで暗号文文字列を復号化するより良い方法
CBC モードではなく、CTS モードを使用しています。したがって、最初のステップは正しいモードを使用することです ;)
以下は、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"
2 番目にやりたいことは、文字列を 16 進数からバイナリに変更することです。これは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 を手動で復号化するつもりでしたが、時間がありません。
私は本当にこれをどうすればいいのかわかりません... AES を ECB モードで操作してから、自分で XOR を実行しますか? その場合は、ArrayXorSinkを検討してください。