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

走远了吗. 提交于 2020-01-06 07:31:29

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/52619332/c-openssl-encryption-using-cbc-cipher-block-chaining-mode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!