4

I tried to implement a "very" simple encryption/decryption example. I need it for a project where I would like to encrypt some user information. I can't encrypt the whole database but only some fields in a table.

The database and most of the rest of the project works, except the encryption: Here is a simplified version of it:

#include <openssl/aes.h>
#include <openssl/evp.h>
#include <iostream>
#include <string.h>

using namespace std;

int main()
{
    /* ckey and ivec are the two 128-bits keys necessary to
       en- and recrypt your data.  Note that ckey can be
       192 or 256 bits as well
     */

    unsigned char ckey[] =  "helloworldkey";
    unsigned char ivec[] = "goodbyworldkey";

    int bytes_read;
    unsigned char indata[AES_BLOCK_SIZE];
    unsigned char outdata[AES_BLOCK_SIZE];
    unsigned char decryptdata[AES_BLOCK_SIZE];

    /* data structure that contains the key itself */
    AES_KEY keyEn;

    /* set the encryption key */
    AES_set_encrypt_key(ckey, 128, &keyEn);

    /* set where on the 128 bit encrypted block to begin encryption*/
    int num = 0;

    strcpy( (char*)indata , "Hello World" );
    bytes_read = sizeof(indata);

    AES_cfb128_encrypt(indata, outdata, bytes_read, &keyEn, ivec, &num, AES_ENCRYPT);
    cout << "original data:\t" << indata << endl;
    cout << "encrypted data:\t" << outdata << endl;

    AES_cfb128_encrypt(outdata, decryptdata, bytes_read, &keyEn, ivec, &num, AES_DECRYPT);
    cout << "input data was:\t" << decryptdata << endl;
    return 0;
}

But the output of "decrypted" data are some random characters, but they are the same after every execution of the code. outdata changes with every execution...

I tried to debug and search for a solution, but I couldn't find any solution for my problem.
Now my question, what is going wrong here? Or do I completely misunderstand the provided functions?

jww
  • 97,681
  • 90
  • 411
  • 885
user3059230
  • 65
  • 2
  • 7
  • Have you tried also using `AES_set_decrypt_key`? Seems weird to me, but hey, the function must have a use. – Maarten Bodewes May 02 '14 at 17:18
  • 1
    Are you sure you want to use the low level AES encryption functions? It's a much better idea to use the high level EVP interface. – shanet May 02 '14 at 17:46
  • Also, somewhat unrelated to your question, but don't print encrypted data to stdout. It's not ASCII data. Encode it with base64 first if you must print it out. – shanet May 02 '14 at 17:47
  • 1
    You're also using "helloworldkey" as a 128bit key, but that array is only 14 characters (including the NUL terminator) or 112bits. Same with the IV. – shanet May 02 '14 at 17:51
  • You should *not* use `AES_encrypt` and friends. You should be using `EVP_*` functions. See [EVP Symmetric Encryption and Decryption](https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption) on the OpenSSL wiki. In fact, you should probably be using authenticated encryption because it provides *both* confidentiality and authenticity. See [EVP Authenticated Encryption and Decryption](https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption) on the OpenSSL wiki. – jww May 15 '15 at 20:29
  • you cannot use cout with char array! – yelliver Dec 05 '16 at 09:42

1 Answers1

8

The problem is that AES_cfb128_encrypt modifies the ivec (it has to in order to allow for chaining). Your solution is to create a copy of the ivec and initialize it before each call to AES_cfb128_encrypt as follows:

const char ivecstr[AES_BLOCK_SIZE] = "goodbyworldkey\0";
unsigned char ivec[AES_BLOCK_SIZE];
memcpy( ivec , ivecstr, AES_BLOCK_SIZE);

Then repeat the memcpy before your second call to AES_cfb128_encrypt.

Note 1: Your initial vector was a byte too short, so I put an explicit additional \0 at the end of it. You should make sure all of your strings are of the correct length when copying or passing them.

Note 2: Any code which uses encryption should REALLY avoid using strcpy or any other copy of unchecked length. It's a hazard.

Edward
  • 6,964
  • 2
  • 29
  • 55