caesmbedtls

why aes encryption result from mbedtls is different than java and online tool result?


I have following c code snippet that try to encrypt "hello" using AES CBC encryption cipher. but some how, the encryption result from below code (mbedtls), is different from Java code result and online tool result. I'm a c programming language newbie, I tried to google around, and can't figure out where is the problem.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mbedtls/aes.h"
#include "mbedtls/base64.h"
#include "mbedtls/md5.h"
#include "mbedtls/cipher.h"

int main() 
{
    unsigned char key[] = "6c74ea86f5c867f1"; 
    unsigned char iv[] = "5e64fe04bfd8363b"; 
    unsigned char input[100] = {0};

    memset(input, 0, 100 );
    strcpy(input, "hello");


    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes); 

    mbedtls_aes_setkey_enc( &aes, key, 128 );
    mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, 16, iv, input, input );

    int i;
    for (i=0; i<100; i++) 
    {
        printf("%x ",input[i]);
    }
    printf("\n");

    size_t outlen=0;
    char *dst = (char *)malloc(sizeof(char)*200);

    mbedtls_base64_encode(dst, 100, &outlen, input, 16);

    printf("cipher is: %s \n", dst);

                        
}

the code above print "cipher is: W9T3jTvbtfYGUZ3yXkQ6wA== ", but the java encrption result using same key and iv is "Fr00ZupbEBVr4gwL/l+G2w==", and so is the result from https://www.devglan.com/online-tools/aes-encryption-decryption

Can some one help me out?


Solution

  • Your code looks almost correct, I think the issue may lie in:

    mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, 16, iv, input, input );
    

    Because your input buffer is the same as the output buffer.

    Try to use two different buffers (one for the input, and one for the output).

    Then look if that solves the problem.

    The documentation of mbedtls_aes_crypt_cbc says nothing about overlapping input and output buffers.

    Edit:

    I think I've found the culprit.

    It's an issue I've encountered myself in the past too.

    When the input isn't 16 bytes aligned, there are multiple ways to "pad" the input.

    In your code, you fill up the buffer with zeros 0 but there are ways to pad the input with something else than 0.

    Probably mbedtls has a function that lets you pad your input to an existing standard (the one the website devglan.com uses).

    Quoting another answer from a different stackexchange site:

    There are multiple methods to pad data, which can completely undermine the compatibility of a given encryption program with others. The most used padding method in symmetric ciphers and mode of operation is certainly PKCS#7.

    (emphasis mine)

    So you probably want "PKCS#7" padding for your input data.

    And, a commentor on an issue said this about using mbedtls_aes_* functions directly:

    I should add that it's very likely that you should not be using mbedtls_aes_xxx functions. They're mainly intended as building blocks for higher-level APIs, not for direct use by applications. Hard-coding cryptographic algorithms in application code is a bad idea: If you’re typing the letters A-E-S into your code, you’re doing it wrong.

    Which would make sense, as with the mbedtls_cipher_* functions you can specify how to pad the input data (mbedtls_cipher_set_padding_mode which defaults to PKCS#7, by the way).

    Bottom line:

    I think you should try to solve your problem with mbedtls_cipher_* functions instead of doing it with mbedtls_aes_*.