Peng Zhanglong
Peng Zhanglong

Reputation: 15

C - OpenSSL encryption using CBC (Cipher Block Chaining) mode

I am using C-API of OpenSSL, but I am confused on how IV (Initialization Vector) is used in OpenSSL.

Say, I have

plaintext.txt file = "This is a top secret."
Key                = "example#########"
IV                 = 010203040506070809000a0b0c0d0e0f

when I encrypt this using OpenSSL AES-128-CBC, I should get:

e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22

Which is true when I try this (key converted to hex):

openssl enc -aes-128-cbc -e -in plaintext.txt -out ciphertext.bin 
-K 6578616d706c65232323232323232323 -iv 010203040506070809000a0b0c0d0e0f

I get:

xxd -p ciphertext.bin 
e5accdb667e8e569b1b34f423508c15422631198454e104ceb658f5918800c22

But I got different ciphertext thing using C

char plaintext[] = "This is a top secret.";

unsigned char iv[16] = {
    0x01, 0x02, 0x03, 0x04, 
    0x05, 0x06, 0x07, 0x08, 
    0x09, 0x00, 0x0A, 0x0B, 
    0x0C, 0x0D, 0x0E, 0x0F
};

unsigned char ciphertext[] = {
    0xe5, 0xac, 0xcd, 0xb6, 
    0x67, 0xe8, 0xe5, 0x69, 
    0xb1, 0xb3, 0x4f, 0x42, 
    0x35, 0x08, 0xc1, 0x54, 
    0x22, 0x63, 0x11, 0x98, 
    0x45, 0x4e, 0x10, 0x4c, 
    0xeb, 0x65, 0x8f, 0x59, 
    0x18, 0x80, 0x0c, 0x22
};

key (example) is in a words.txt file.


My encryption process:

while(fgets(words, 16, wordsfile)) { //for getting key and padding
    index = strlen(words) - 1;       //key "example" is the last word in words.txt
    while(index < 16) {
        words[index] = 0x20;
        index++;
    }
    words[index] = '\0';
    EVP_CIPHER_CTX ctx;
    EVP_CIPHER_CTX_init(&ctx);
    EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, words, iv, 1);
    EVP_CipherUpdate(&ctx, outbuf, &outlen, plaintext, strlen(plaintext));
    EVP_CipherFinal_ex(&ctx, outbuf + outlen, &templ);
    outlen += templ;
    EVP_CIPHER_CTX_cleanup(&ctx);
}

When I check the ciphertext matches to key "example", I got a completely different ciphertext. Which part I was wrong? I am assuming the format of IV or the way I implemented IV is wrong.

Upvotes: 0

Views: 1587

Answers (1)

Reinier Torenbeek
Reinier Torenbeek

Reputation: 17363

It looks like you are pretty close. By narrowing down the problem to just the encryption, the correct ciphertext can be produced. So in stead of reading the key from the file, define it as an array of unsigned chars, similar to what you did for the other variables:

unsigned char key[]={0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23};

Then the following code (reusing your variables) shows the successful encryption:

EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(),NULL, key, iv, 1);
EVP_CipherUpdate(&ctx, outbuf, &outlen, (unsigned char *)plaintext, strlen(plaintext));
EVP_CipherFinal_ex(&ctx, outbuf+outlen, &templ);
outlen+=templ;
EVP_CIPHER_CTX_cleanup(&ctx);
int cmpres = memcmp(outbuf, ciphertext, sizeof(ciphertext));
printf("cmpres is %d, sizeof(ciphertext) is %lu, outlen is %d\n",
    cmpres, sizeof(ciphertext), outlen);

because it prints

$ ./main
cmpres is 0, sizeof(ciphertext) is 32, outlen is 32

This means that the problem is in how you read the key from the file. That is much easier to analyze than cryptographic issues :-) and I will leave it up to you to figure out that part...

By the way, make sure to check all return codes for your OpenSSL calls, it will help you to detect error situations.

Upvotes: 2

Related Questions