如何使用mbedtls以aes方式加密字符串?

时间:2017-12-07 07:16:23

标签: c encryption polarssl mbedtls

我们都知道mbedtls库是一个非常轻量级的c库。我想使用库来加密字符串。所以我有这样的功能:

aes_encrypt.h:

#ifndef AES_ENCRYPT_H
#define AES_ENCRYPT_H

#define BOOL int
#define TRUE 1
#define FALSE 0

extern const unsigned char key[16];

BOOL ENC_STR(unsigned char *plain, size_t plain_len, 
             unsigned char *cipher, size_t *cipher_len);
#endif

和实施:

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

BOOL ENC_STR(unsigned char *plain, size_t plain_len, unsigned char *cipher, size_t *cipher_len)
{
BOOL ret = FALSE;

// Prepare the cipher context
const mbedtls_cipher_info_t *cipher_info;
mbedtls_cipher_context_t cipher_ctx;
mbedtls_cipher_init(&cipher_ctx);

if ((cipher_info = mbedtls_cipher_info_from_type(AES_PARM)) == NULL)
{
    printf("Cipher Info ERR!\n");
    ret = -1;
    goto EXIT;
}

if ( (ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0)
{
    printf("Cipher Setup ERR!\n");
    goto EXIT;
}

if ( (ret = mbedtls_cipher_setkey(&cipher_ctx, KEY, cipher_info->key_bitlen, MBEDTLS_ENCRYPT)) != 0)
{
    printf("Cipher SetKey ERR!\n");
    goto EXIT;
}

// if ( (ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, 1)) != 0) {
//     printf("Cipher SetPadding ERR!\n");
//     goto EXIT;
// }


if ( (ret = mbedtls_cipher_reset(&cipher_ctx)) != 0)
{
    printf("Cipher Reset ERR!\n");
    goto EXIT;
}

// encrypt
if ((ret = mbedtls_cipher_update(&cipher_ctx, plain, plain_len, cipher, cipher_len)) != 0) {
    printf("Cipher Update ERR!\n");
    goto EXIT;
}

EXIT:
    if (ret != TRUE) {
        char buf[1024] = {0};
        mbedtls_strerror(ret, buf, 1024);
        printf("Error Msg:\t%s\n", buf);
    }

    mbedtls_cipher_free(&cipher_ctx);
    return ret;
}

我把这个函数称为bellow:

unsigned char *plain = (unsigned char*)"hello world";
size_t plain_len = 12;
unsigned char cipher[128] = {0};
size_t cipher_len = -1;
printf("the encrypt result is:\t%d\n", ENC_STR(plain, plain_len, cipher, &cipher_len));

我得到的错误信息如下:

CIPHER - Decryption of block requires a full block

任何人都可以帮助我解释错误信息的含义吗?感谢。

3 个答案:

答案 0 :(得分:0)

说明:

  

CIPHER - 块的解密需要一个完整的块
  任何人都可以帮助我解释错误信息的含义是什么?

AES是block cipher,这意味着它被实现为当时加密128位块。不多也不少。

因此,如果源数据短于一个块,则需要使用一些padding来确保将数据延长到所需的长度。

通常,为了加密任何长度的数据,我们使用mode of operation。有一些不需要任何填充(CTR,CFB,OFB,..)

您的加密仍然远非安全 - 您需要IV(盐)和authentication tag

  

我们都知道mbedtls库是一个非常轻量级的c库

显然,mbedtls已经支持多种操作模式,由你自己选择

答案 1 :(得分:0)

您可以使用mbedtls_cipher_crypt()加密完整缓冲区,也可以通过多次调用mbedtls_cipher_update()来加密缓冲区。
要添加填充,您应该致电mbedtls_cipher_set_padding_mode。但是,如code所示,默认填充方案是PKCS7,如果定义了MBEDTLS_CIPHER_PADDING_PKCS7
根据您的代码,您似乎正在使用AES ECB(您尚未设置任何IV)。 AES ECB不支持填充,出于安全考虑,它仅接受AES BLOCK大小的输入(16字节)。如下所述,您应该考虑使用AES CBC进行操作,因为AES ECB对于超过16个字节的输入不安全,并且您的函数应尽可能通用以支持大字符串。

答案 2 :(得分:0)

您需要通过调用mbedtls_cipher_finish来完成加密。

使用finish的原因是需要添加填充,而update却没有这样做。即使源数据的长度为N * BlockSize,PKCS7填充方案(默认情况下也会使用)总是添加一些内容。

https://tls.mbed.org/api/cipher_8h.html#a6678691c02cb3f1322b2179987bfffb2