0

I'm trying to encrypt a string using AES encryption provided by Crypto++ library API, version 5.6.0, linked statically

string AESEncryptor::encrypt(const string& plain)
{
    string ciphertext_buffer;

    // Hex decode symmetric key:
    HexDecoder decoder;
    decoder.Put((byte *)PRIVATE_KEY, 32 * 2);
    decoder.MessageEnd();
    word64 size = decoder.MaxRetrievable();
    char *decoded_key = new char[size];
    decoder.Get(reinterpret_cast<byte*>(decoded_key), size);

    // Generate Cipher, Key, and CBC
    byte key[AES::MAX_KEYLENGTH], iv[AES::BLOCKSIZE];
    StringSource(reinterpret_cast<const char *>(decoded_key), true, 
        new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)));
    memset(iv, 0x00, AES::BLOCKSIZE);

    CBC_Mode<AES>::Encryption Encryptor(key, sizeof(key), iv);
    StringSource(plain, true, 
        new StreamTransformationFilter(Encryptor, new HexEncoder(new StringSink(ciphertext_buffer))));
    return ciphertext_buffer;
}

On the function exit I'm receiving the following exception, while trying to call the std::string move constructor to return the value:

Exception thrown: write access violation. this was 0xDDDDDDDD.

Looked like StringSink "owns" returned std::string some way and deletes it before trying to return, however I tried to assign it to another std::string and got the same exception.

Same exception appears while returning any other string, so it seems memory corrupted some way

jww
  • 97,681
  • 90
  • 411
  • 885

1 Answers1

0
StringSource(plain, true, 
    new StreamTransformationFilter(Encryptor,
        new HexEncoder(new StringSink(ciphertext_buffer))));

return ciphertext_buffer;

This code is mostly OK, but you should avoid the anonymous declarations.

Exception thrown: write access violation. this was 0xDDDDDDDD.

0xDDDDDDDD is the "dead memory" bit pattern There's quite a few issues with the code, and its hard to say which is causing you to use the dead memory. Maybe PRIVATE_KEY is smaller than 32 * 2 bytes?

You should do four things:

  • Upgrade to Crypto++ 5.6.4 (5.6.0 is from 2009)
  • Turn on memory checking with flags like _CRTDBG_LEAK_CHECK_DF (see test.cpp and main for an example)
  • Stop using anonymous declarations (I've seen destructors run too soon because of them)
  • Use EAX Mode sample code from the Crypto++ wiki as a starting point

// Generate Cipher, Key, and CBC
byte key[AES::MAX_KEYLENGTH], iv[AES::BLOCKSIZE];
StringSource(reinterpret_cast<const char *>(decoded_key), true, 
    new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)));

Use HKDF from Crypto++ 5.6.3 and above.


memset(iv, 0x00, AES::BLOCKSIZE);

I believe this destroys some of CBC's security properties. You should use an Authenticated Encryption mode. It relieves you of some of the details, like generating random IVs. It also has better security properties than CBC alone.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • We can quibble about whether that should read "some" or "most" of CBC's security properties - but definitely always using an IV of zero is a no-no. In particular, it means that if two plain-texts have identical first blocks, then the first blocks of the cipher text will be identical too - which may be more than enough for an attacker to gain meaningful information from. – Martin Bonner supports Monica Sep 20 '16 at 15:32
  • Migration to Crypto++ 5.6.4 and new API helped, thanks –  Sep 21 '16 at 04:27