midCat
midCat

Reputation: 123

I can't decrypt the string after I encrypt the string with PolarSSL AES-CBC

I wrote a program to encrypt a string with PolarSSL AES-CBC

this is my code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <polarssl/aes.h>
#include <polarssl/havege.h>

int main()
{
    char buff[2][64] = {"Who can tell me WHY?", ""};
    havege_state hs;
    int retval;
    unsigned char IV[16];

    aes_context enc_ctx;
    aes_context dec_ctx;

    aes_setkey_enc(&enc_ctx, "password", 256);
    aes_setkey_dec(&dec_ctx, "password", 256);

    havege_init(&hs);
    havege_random(&hs, IV, 16);

    //encrypt
    aes_crypt_cbc(&enc_ctx, AES_ENCRYPT, 64, IV, buff[0], buff[1]);
    havege_random(&hs, IV, 16);

    //decrypt
    aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV, buff[1],buff[0]);

    printf("After decrypt:%s\n", buff[0]);
    return 0;
}

But when I run it, I just got the wrong text after it decrypt.

I don't understand AES algorithm clearly, because my english is very bad, It's too hard for me to read some articles.

-------------------------Added By midCat--------------------------------------------

I followed you advice, and Change me code now I use the same IV and 256-bit key, this is the new code

int main()
{
    char buff[2][64] = {"ABCDEFGHIJKLMN", ""};
    havege_state hs;
    int retval;
    unsigned char IV[16];
    unsigned char IV2[16];
    unsigned char key[32];

    aes_context enc_ctx;
    aes_context dec_ctx;

    havege_init(&hs);
    havege_random(&hs, IV, 16);
    havege_random(&hs, key, 32);
    strncpy(IV, IV2, 16);           //copy IV

    aes_setkey_enc(&enc_ctx, key, 256);
    aes_setkey_dec(&dec_ctx, key, 256);


    //encrypt
    aes_crypt_cbc(&enc_ctx, AES_ENCRYPT, 64, IV, buff[0], buff[1]);
    printf("Before encrypt:%s\n", buff[0]);

    //decrypt
    aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);
    printf("After decrypt:%s\n", buff[0]);
    return 0;
}

I compiler it, and run for many times, got the same output:

Before encrypt:ABCDEFGHIJKLMN
After decrypt:ABCDEFGHYC
                        LMN

How to got IV?

Upvotes: 3

Views: 2843

Answers (2)

Daniel Roethlisberger
Daniel Roethlisberger

Reputation: 7065

You are using a random IV to decrypt. That is wrong. You need the same IV for decryption as you used for encryption. Simply remove the second call to

havege_random(&hs, IV, 16);

between the encrypt and the decrypt.

Also make sure to use a 32 byte char array as second argument to aes_setkey_enc and aes_setkey_dec because you are reading past the end of the string as it is now. Depending on the compiler it might lead to different keys being used for encryption and decryption (and thus, fail).

(Edit for second half of question)

Change this:

strncpy(IV, IV2, 16);           //copy IV

to this:

memcpy(IV2, IV, 16);           //copy IV

That's memcpy instead of strncpy because the IV is random data which can contain the string terminator '\0', and the first argument to both of these functions is the destination, not the source. You copied a string from IV2 to IV instead of memory from IV to IV2.

And to answer the question on how to get the IV for decryption: Normally, the IV is just sent along with the ciphertext. Each IV must only once be used once and it must not be predictable, but it is not necessary to keep it secret. A common construction is to choose a random IV for every message and simply prepend the IV to the ciphertext or to store it in a file header, depending on the scenario.

That being said, I agree with the advice to not construct your own crypto protocols using crypto primitives unless you know what you are doing.

Upvotes: 4

dnaq
dnaq

Reputation: 2244

EDIT: As Daniel pointed out in his answer, one big problem is that you are trying to use a random IV to decrypt (which will not give you the results you expect). However, I suggest that you read the rest of this answer as well.

First of all, aes_set_key_enc and aes_set_key_dec do not take passwords as input, they take keys. A key should be a completely random value as long as the key length (a random string of 32 bytes in your case, since you want to use a 256-bit key).

In your case you're calling aes_set_key_enc/aes_set_key_dec with a short password, but telling it that it should expect a 256-bit key, this will lead to these functions using memory outside of your password as part of the key, and will lead to the encryption and decryption keys to be different.

To recap, AES (or any cipher algorithm for that matter) expects random keys, the algorithms themselves have no concept of expanding a password to a key.

If you want to use a password as a key you need some function that expands a non-random password into a pseudo-random key. The only sane way to do this is to use a function that is designed to be cryptographically secure, but also slow, this is to mitigate the risk of brute-force attacks on the password.

Good functions to use are Colin Percivals scrypt, bcrypt or PBKDF2 of which I would recommend scrypt the most.

However, I want to stress that you probably shouldn't be working at this abstraction level at all. The primitives that you are using (block ciphers, CBC-mode) are at a really low abstraction level, and building a cryptosystem using those primitives can be really dangerous. For example you do not use any kind of authentication on your ciphertext, which might open up your implementation to chosen ciphertext attacks.

I think that the best way to if you want to use cryptography in your application is to try to work at a higher abstraction level, for example using Dan Bernsteins excellent NaCl or Googles KeyCzar.

To recap, your specific problem can be solved by using 256-bit keys, but you should think twice about implementing your own cryptosystem at this abstraction level.

Upvotes: 4

Related Questions