- 由于mbedtls主要支持TCP的TLS传输实现,由ARM公司加持,目前这个库的代码质量非常高,也可以用在其他加密解密领域,比如AES、DES、chacha20等加密,当然和libsodium实现互补,有些实现也必须用libsodium更好一些,不过这两个库的代码质量都很高。
- 示例代码展现了AES-256-ECB的加密如何使用,由于库里面有很多加密支持,可以参考mbedtls github原始代码的cipher_wrap.c实现,这里面实现了统一API封装,方便使用,只需要初始化时给出对应的类型参数,即可获取相应handle方便使用。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
unsigned char key[] = {
0x01, 0x02, 0x34, 0x78, 0x78, 0x23, 0x34, 0x11,
0x02, 0x03, 0x34, 0x78, 0x78, 0x23, 0x34, 0x12,
0x03, 0x04, 0x34, 0x78, 0x78, 0x23, 0x34, 0x13,
0x04, 0x05, 0x34, 0x78, 0x78, 0x23, 0x34, 0x14
};
#define DEBUG_LEVEL 1
static void add_pkcs_padding(unsigned char *output, size_t output_len,
size_t data_len)
{
size_t padding_len = output_len - data_len;
unsigned char i;
for(i = 0; i < padding_len; i++)
output[data_len + i] = (unsigned char) padding_len;
}
int main(int argc, char *argv[])
{
int ret = 0;
int i = 0;
mbedtls_cipher_context_t cipher_ctx_enc;
mbedtls_cipher_context_t cipher_ctx_dec;
mbedtls_cipher_init(&cipher_ctx_enc);
mbedtls_cipher_init(&cipher_ctx_dec);
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif
printf("start cipher test\n");
const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_string("AES-256-ECB");
if((ret = mbedtls_cipher_setup(&cipher_ctx_enc,
cipher_info)) != 0)
{
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
goto Cleanup;
}
if((ret = mbedtls_cipher_setup(&cipher_ctx_dec,
cipher_info)) != 0)
{
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
goto Cleanup;
}
if((ret = mbedtls_cipher_setkey(&cipher_ctx_enc, key,
cipher_info->key_bitlen,
MBEDTLS_ENCRYPT)) != 0)
{
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
goto Cleanup;
}
if((ret = mbedtls_cipher_setkey(&cipher_ctx_dec, key,
cipher_info->key_bitlen,
MBEDTLS_DECRYPT)) != 0)
{
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
goto Cleanup;
}
size_t olen = 0;
size_t index = 0;
FILE *file = fopen("/tmp/test.txt", "r");
if(!file)
{
exit(-1);
}
fseek(file, 0L, SEEK_END);
int length = ftell(file);
fseek(file, 0L, SEEK_SET);
int plainLen = length;
int padding = length % cipher_ctx_enc.cipher_info->block_size;
if(padding > 0)
{
plainLen += (cipher_ctx_enc.cipher_info->block_size - padding);
}
printf("padding:%d plainLen:%d\n",padding,plainLen);
uint8_t *message = (uint8_t *)calloc(plainLen, sizeof(uint8_t));
if(!message)
{
ret = -1;
goto Cleanup;
}
fread(message, sizeof(uint8_t), length, file);
fclose(file);
add_pkcs_padding(message, plainLen, length);
uint8_t *cipherText = (uint8_t *)calloc(plainLen, sizeof(char));
if(!cipherText)
{
ret = -1;
goto Cleanup;
}
printf("start file encrypt\n");
while(index < plainLen)
{
if((ret = mbedtls_cipher_crypt(&cipher_ctx_enc,
NULL,
0,
message + index, cipher_ctx_enc.cipher_info->block_size,
cipherText + index, &olen)) != 0)
{
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret);
goto Cleanup;
}
index += cipher_ctx_enc.cipher_info->block_size;
}
printf("encrypt cipher text:\n");
for(i=0;i<plainLen;i++)
{
printf("%02X",cipherText[i]);
}
printf("\n");
index = 0;
memset(message, 0, plainLen);
while(index < plainLen)
{
if((ret = mbedtls_cipher_crypt(&cipher_ctx_dec,
NULL,
0,
cipherText + index, cipher_ctx_dec.cipher_info->block_size,
message + index, &olen)) != 0)
{
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret);
goto Cleanup;
}
index += cipher_ctx_dec.cipher_info->block_size;
}
printf("decrypt file ok:\n");
for(i=0;i<length;i++)
{
printf("%c",message[i]);
}
printf("\n");
Cleanup:
if(message)
free(message);
if(cipherText)
free(cipherText);
mbedtls_cipher_free(&cipher_ctx_enc);
mbedtls_cipher_free(&cipher_ctx_dec);
return 0;
}
|