环境
操作系统:WSL2-Ubuntu22.04
在线AES计算网站:SSLeye
代码中需要用到mbedtls和Base64,可以根据上述链接获取
简介
高级加密标准(Advanced Encryption Standard,AES),是一种对称加密方式。AES支持三种加密方式:AES128,AES192,AES256,AES128标识密钥长度为128bit,AES128运算速度最快,AES256安全性最佳,三种方式的本质区别是加密轮数不同。
模式
一共有4种加密模式,即ECB、CBC、CFB、OFB,本文仅讲解最常见的ECB、CBC模式,有机会更新后续两种。
ECB模式:
优点:1.简单;2.有利于并行计算;3.误差不会被传送
缺点: 1.不能隐藏明文的模式(例如加密一张图片,虽然看不到原图,但是可能看到其轮廓);2.可能对明文进行主动攻击
CBC模式:
优点:1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准
缺点:1.不利于并行计算;2.误差传递;3.需要初始化向量IV
API简介
初始化/释放句柄
void mbedtls_aes_init( mbedtls_aes_context *ctx );
void mbedtls_aes_free( mbedtls_aes_context *ctx );
生成加/解密的密钥
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits );
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits );
ctx:句柄
key:密钥,必须16、24或32Bytes
keybits:密钥长度,128、192或256bit
ECB加/解密,每次执行一个块,一个块为16Bytes,明文不足一个块的需要进行补位
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
ctx:句柄
mode:MBEDTLS_AES_ENCRYPT或MBEDTLS_AES_DECRYPT
input:输入指针,长度不足一个块16Bytes的需要进行补位
output:输出指针,长度为一个块16Bytes
CBC加/解密,可以加密任意长度的明文(必须补齐为16的整倍数)
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
ctx:句柄
mode:MBEDTLS_AES_ENCRYPT或MBEDTLS_AES_DECRYPT
length:输入长度(必须补齐为16的整倍数)
iv:初始化向量,必须为16字节且可读写。每个块运算完之后会生成新的向量传给下一个块运算,所以加密完成后此值会改变,解密时应该重新赋值。
input:输入指针
output:输出指针
ECB加/解密DEMO
#include <string.h>
#include <stdio.h>
#include "mbedtls/aes.h"
#include "base64.h"
int main(void)
{
mbedtls_aes_context aes_ctx;
unsigned char aes_in[16] = "123456789abcdef";
unsigned char aes_out[16];
unsigned char b64_out[1024] = {0};
mbedtls_aes_init(&aes_ctx);
/****************************加密****************************/
// 加载加密密钥
mbedtls_aes_setkey_enc(&aes_ctx, "1234567890123456", 128);
// 加密 一次执行一个块即16BYTE
mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, aes_in, aes_out);
// 以base64编码形式打印
base64_encode(aes_out, 16, b64_out);
printf("%s\r\n", b64_out);
// ahBLMYUa/tgH+sxQNzZxyw==
/****************************解密****************************/
memset(aes_in, 0, 16);
// 加载解密密钥
mbedtls_aes_setkey_dec(&aes_ctx, "1234567890123456", 128);
// 解密
mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_DECRYPT, aes_out, aes_in);
printf("%s\r\n", aes_in);
// 123456789abcdef
/****************************End****************************/
mbedtls_aes_free(&aes_ctx);
}
CBC加/解密DEMO
#include <string.h>
#include <stdio.h>
#include "mbedtls/aes.h"
#include "base64.h"
int main(void)
{
mbedtls_aes_context aes_ctx;
unsigned char ivec[16] = "1234567890123456";
unsigned char aes_in[32] = "1234567890123456789";
unsigned char aes_out[32];
unsigned char b64_out[1024] = {0};
mbedtls_aes_init(&aes_ctx);
/****************************加密****************************/
// 加载加密密钥
mbedtls_aes_setkey_enc(&aes_ctx, "1234567890123456", 128);
// 加密
mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, 32, ivec, aes_in, aes_out);
// 以base64编码形式打印
base64_encode(aes_out, 32, b64_out);
printf("%s\r\n", b64_out);
// 2LWYSMdnDJSym1TSN54uer0JwNlyHlQcjnl1uQ7ofOw=
/****************************解密****************************/
memset(aes_in, 0, 32);
// 加载解密密钥
mbedtls_aes_setkey_dec(&aes_ctx, "1234567890123456", 128);
memcpy(ivec, "1234567890123456", 16);
// 解密
mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, 32, ivec, aes_out, aes_in);
printf("%s\r\n", aes_in);
// 1234567890123456789
/****************************End****************************/
mbedtls_aes_free(&aes_ctx);
}