본문 바로가기

개발자료/Openssl

AES-CTR

openssl 을 활용한 AES-CTR (key, IV)


reference: https://www.openssl.org/docs/manmaster/man3/EVP_EncryptInit_ex.html


#include <string.h>

#include <glib.h>

#include <openssl/aes.h> //for AES_BLOCK_SIZE

#include <openssl/err.h> //for ERR_error_string()

#include <openssl/evp.h>


static gboolean encrypt_data_by_aes_ctr (guint8 **out_data,

                                         gint    *out_data_len,

                                         guint8  *in_data,

                                         gint     in_data_len,

                                         guint8  *key,

                                         guint8  *iv)

{

        gboolean ret = FALSE;

        EVP_CIPHER_CTX *ctx = NULL;

        gint c_len, f_len;

        guint8 *ciphertext;


        g_assert_nonnull (out_data);

        g_assert_nonnull (in_data);

        g_assert_nonnull (key);

        g_assert_nonnull (iv);


        c_len = in_data_len + AES_BLOCK_SIZE;

        f_len = 0;

        ctx = EVP_CIPHER_CTX_new ();

        ciphertext = g_malloc (c_len);


        EVP_EncryptInit_ex (ctx, EVP_aes_128_ctr (), NULL, key, iv);


        if (EVP_EncryptUpdate (ctx, ciphertext, &c_len, in_data, in_data_len) == 0) {

                g_error ("fail EVP_EncryptUpdate: %s",

                         ERR_error_string (ERR_peek_last_error (), NULL));

                g_free (ciphertext);

                goto exit;

        }


        if (EVP_EncryptFinal_ex (ctx, ciphertext + c_len, &f_len) == 0) {

                g_error ("fail EVP_EncryptFinal_ex: %s",

                         ERR_error_string (ERR_peek_last_error (), NULL));

                g_free (ciphertext);

                goto exit;

        }


        *out_data = ciphertext;

        *out_data_len = c_len + f_len;

        ret = TRUE;


exit:

        EVP_CIPHER_CTX_free (ctx);

        return ret;

}


static gboolean encrypt_data_by_aes_ctr_with_keying_data (guint8 **out_data,

                                                          gint    *out_data_len,

                                                          guint8  *in_data,

                                                          gint     in_data_len,

                                                          guint8  *key_data,

                                                          gint     key_data_len)

{

        gboolean ret = FALSE;

        gint ret_openssl;

        guint8 key_gen[16], iv_gen[16];


        ret_openssl = EVP_BytesToKey (EVP_aes_128_ctr (), EVP_sha1 (), NULL,

                                      key_data, key_data_len, 0, key_gen, iv_gen);

        if (ret_openssl != 16) {

                g_error ("Key size is %d bytes - should be 16 bytes", ret_openssl);

                goto exit;

        }


        ret = encrypt_data_by_aes_ctr (out_data, out_data_len,

                                       in_data, in_data_len, key_gen, iv_gen);


exit:

        return ret;

}

static gboolean decrypt_data_by_aes_ctr (guint8 **out_data,

                                         gint    *out_data_len,

                                         guint8  *in_data,

                                         gint     in_data_len,

                                         guint8  *key,

                                         guint8  *iv)

{

        gboolean ret = FALSE;

        EVP_CIPHER_CTX *ctx = NULL;

        gint p_len, f_len;

        guint8 *plaintext;


        g_assert_nonnull (out_data);

        g_assert_nonnull (in_data);

        g_assert_nonnull (key);

        g_assert_nonnull (iv);


        p_len = 0;

        f_len = 0;

        plaintext = g_malloc (in_data_len);


        ctx = EVP_CIPHER_CTX_new ();

        EVP_DecryptInit_ex (ctx, EVP_aes_128_ctr (), NULL, key, iv);


        if (EVP_DecryptUpdate (ctx, plaintext, &p_len, in_data, in_data_len) == 0) {

                g_error ("fail EVP_DecryptUpdate: %s",

                         ERR_error_string (ERR_peek_last_error (), NULL));

                g_free (plaintext);

                goto exit;

        }


        if (EVP_DecryptFinal_ex (ctx, plaintext + p_len, &f_len) == 0) {

                g_error ("fail EVP_DecryptFinal_ex: %s",

                         ERR_error_string (ERR_peek_last_error (), NULL));

                g_free (plaintext);

                goto exit;

        }


        *out_data = plaintext;

        *out_data_len = p_len + f_len;

        ret = TRUE;


exit:

        EVP_CIPHER_CTX_free (ctx);

        return ret;

}


static gboolean decrypt_data_by_aes_ctr_with_keying_data (guint8 **out_data,

                                                          gint    *out_data_len,

                                                          guint8  *in_data,

                                                          gint     in_data_len,

                                                          guint8  *key_data,

                                                          gint     key_data_len)

{

        gboolean ret = FALSE;

        gint ret_openssl;

        guint8 key_gen[16], iv_gen[16];


        ret_openssl = EVP_BytesToKey (EVP_aes_128_ctr (), EVP_sha1 (), NULL,

                                      key_data, key_data_len, 0, key_gen, iv_gen);

        if (ret_openssl != 16) {

                g_error ("Key size is %d bytes - should be 16 bytes", ret_openssl);

                goto exit;

        }


        ret = decrypt_data_by_aes_ctr (out_data, out_data_len,

                                       in_data, in_data_len, key_gen, iv_gen);


exit:

        return ret;

}


void main()

{

        gint i;


        gint encrypted_len;

        guint8 *encrypted;


        gint decrypted_len;

        guint8 *decrypted;


        guint8 plain[48] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, };


        if (encrypt_data_by_aes_ctr_with_keying_data (&encrypted, &encrypted_len,

                                                      plain, sizeof(plain),

                                                      "key", sizeof("key"))) {

                g_print ("encrypted value: ");

                for (i = 0; i < encrypted_len; i++) {

                        g_print ("%.2X ", encrypted[i]);

                }

                g_print ("\n");

        }


        if (decrypt_data_by_aes_ctr_with_keying_data (&decrypted, &decrypted_len,

                                                      encrypted, encrypted_len,

                                                      "key", sizeof("key"))) {

                g_print ("decrypted value: ");

                for (i = 0; i < decrypted_len; i++) {

                        g_print ("%.2X ", decrypted[i]);

                }

                g_print ("\n");

        }


        g_assert_cmpmem (plain, sizeof(plain), decrypted, decrypted_len);


        g_free (encrypted);

        g_free (decrypted);

}


'개발자료 > Openssl' 카테고리의 다른 글

RSAES-OAEP encrypt / decrypt  (0) 2018.01.24
RSASSA PKCS1 v1.5  (0) 2018.01.24
HMAC-SHA256  (0) 2018.01.24
SHA256  (0) 2018.01.24