Question

I am trying to decrypt data using AES CBC and CTR mode. The ciphertext has been prepended with the 16 byte IV.

I have my ciphertext data in the following format:

vector<vector<byte>> CBCMessages;
vector<vector<byte>> CBCKeys;
vector<vector<byte>> CTRMessages;
vector<vector<byte>> CTRKeys;

I am using Crypto++ to decrypt the data. This is my code:

for (int i = 0; i < CBCMessages.size(); i++)
{
    std::string decryptedtext;

    // split IV from ciphertext
    byte iv[16];
    std::copy(CBCMessages[i].begin(), CBCMessages[i].begin()+16, iv);
    CBCMessages[i].erase(CBCMessages[i].begin(), CBCMessages[i].begin()+16);

    // this block works fine
    AES::Decryption aesDecryption(&(CBCKeys[i][0]), CBCKeys[i].size());
    CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );
    StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
    stfDecryptor.Put( reinterpret_cast<const unsigned char*>( &(CBCMessages[i][0]) ), CBCMessages[i].size() );
    stfDecryptor.MessageEnd();

    std::cout << decryptedtext << std::endl;
}

for (int i = 0; i < CTRMessages.size(); i++)
{
    std::string decryptedtext;

    // split IV from ciphertext
    byte iv[16];
    std::copy(CTRMessages[i].begin(), CTRMessages[i].begin()+16, iv);
    CTRMessages[i].erase(CTRMessages[i].begin(), CTRMessages[i].begin()+16);

    // this block produces junk
    AES::Decryption aesDecryption(&(CTRKeys[i][0]), CTRKeys[i].size());
    CTR_Mode_ExternalCipher::Decryption ctrDecryption( aesDecryption, iv );
    StreamTransformationFilter stfDecryptor(ctrDecryption, new CryptoPP::StringSink( decryptedtext ) );
    stfDecryptor.Put( reinterpret_cast<const unsigned char*>( &(CTRMessages[i][0]) ), CTRMessages[i].size() );
    stfDecryptor.MessageEnd();

    std::cout << decryptedtext << std::endl;

    // try again with different method - this works fine
    decryptedtext.clear();
    CTR_Mode< AES >::Decryption d;
    d.SetKeyWithIV( &(CTRKeys[i][0]), CTRKeys[i].size(), iv, 16 );
    StringSource( reinterpret_cast<const unsigned char*>( &(CTRMessages[i][0]) ), CTRMessages[i].size(), true, 
        new StreamTransformationFilter( d,
            new StringSink( decryptedtext )
        )
    );

    std::cout << decryptedtext << std::endl;
}

As you can see, the middle block (first block for CTR decryption) produces junk output. Note that this block should actually be pretty identical to the block used for CBC decryption.

The block used for CBC decryption is basically copied from this FAQ entry (answer by 2005-Oct-21 10:38am jeffrey). I have then altered this block to use it for CTR decryption which is when it failed to work. The second CTR block is inspired by the "Sample Program" section here.

What seems to be the problem in the first CTR code block?

Was it helpful?

Solution

It is probably because

AES::Decryption aesDecryption(&(CTRKeys[i][0]), CTRKeys[i].size());

https://upload.wikimedia.org/wikipedia/commons/3/3c/CTR_decryption_2.svg

CTR Mode needs AES::Encryption to decrypt the ciphertest

https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top