本篇总结
使用硬件 AES-128,实现 ECB/CBC 模式的加解密。
🔑 KEIL MDK、UART调试、AES
W55MH32L 集成了硬件 AES-128 加密引擎,支持 ECB(电子密码本)和 CBC(密码块链接)两种工作模式。本示例演示如何使用硬件 AES 对 48 字节明文进行 ECB/CBC 加密并解密验证。
前置工具准备
开始本例程前,请确认以下工具已安装:
- WIZ UartTool V1.0:串口收发测试工具:点击下载
硬件连接
本例程无需外部硬件连接,AES 运算完全在芯片内部完成。USART1 的 TX(PA9) 和 RX(PA10) 通过板载 USB 转串口芯片连接到 DEBUG USB 口,用于输出加密解密结果。
| 引脚 | 功能 | 方向 | 模式 |
| PA9 | USART1_TX | 开发板 → PC | 复用推挽输出 (AF_PP) |
| PA10 | USART1_RX | PC → 开发板 | 浮空输入 (IN_FLOATING) |
工程结构
工程位于 SDK 内 1.SDK\ModuleDemo\AES\,核心文件如下:
AES/
├── USER/
│ ├── main.c ← AES加解密测试 + printf重定向
│ ├── w55mh32_conf.h ← 外设头文件集中包含
│ ├── w55mh32_it.c/h ← 中断服务函数
│ ├── system_w55mh32.c/h← 系统初始化(时钟配置)
│ └── startup_w55mh32.s ← 启动文件
└── SYSTEM/
└── delay/
└── delay.c/h ← SysTick 延时函数
步骤1:AES 结构体与 ECB 加解密
文件:USER/main.c | 函数:AES_Func_Test() — 定义明文、密钥,填充 WIZ_SYN_CRYPTO_CAL_t 结构体后调用 WIZAES_EncDec() 执行 ECB 加密,再用密文作为输入执行解密。
void AES_Func_Test()
{
uint8_t ausPlain[AES_TEST_LEN] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30};
uint8_t ausResult[AES_TEST_LEN] = {0};
uint8_t ausKey[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10};
WIZ_SYN_CRYPTO_CAL_t callAes;
printf("The AES data input is:\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
printf("%02X", ausPlain[i]);
printf("\r\n");
/* ECB 加密 */
memset((uint8_t *)&callAes, 0, sizeof(callAes));
callAes.pu8In = ausPlain;
callAes.ui32InLen = AES_TEST_LEN;
callAes.pu8Out = ausResult;
callAes.ui32OutLen = AES_TEST_LEN;
callAes.pu8Key = ausKey;
callAes.ui32Key = WIZ_AES_KEY_SIZE_128 | WIZ_AES_OP_MODE_ECB | WIZ_AES_OP_MODE_ENCRYPT;
callAes.ui32Ctrl = WIZC_CalcBuffCrc((uint8_t *)&callAes, sizeof(WIZ_SYN_CRYPTO_CAL_t) - 8);
WIZAES_EncDec(&callAes);
printf("The AES (ECB) encrypted message is:\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
printf("%02X", ausResult[i]);
printf("\r\n");
/* ECB 解密 */
memset((uint8_t *)&callAes, 0, sizeof(callAes));
callAes.pu8In = ausResult;
callAes.ui32InLen = AES_TEST_LEN;
callAes.pu8Out = ausPlain;
callAes.ui32OutLen = AES_TEST_LEN;
callAes.pu8Key = ausKey;
callAes.ui32Key = WIZ_AES_KEY_SIZE_128 | WIZ_AES_OP_MODE_ECB | WIZ_AES_OP_MODE_DECRYPT;
callAes.ui32Ctrl = WIZC_CalcBuffCrc((uint8_t *)&callAes, sizeof(WIZ_SYN_CRYPTO_CAL_t) - 8);
WIZAES_EncDec(&callAes);
printf("The AES (ECB) decrypted message is:\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
printf("%02X", ausPlain[i]);
printf("\r\n");
}
ECB 模式中每个 128 位块独立加密,结构简单速度快。通过 ui32Key 字段选择密钥长度(128位)、工作模式(ECB)和操作类型(加密/解密)。ui32Ctrl 字段存放 CRC 校验值,确保结构体数据完整性。
如果你想自定义
- 换密钥 → 修改
ausKey[16] 数组内容
- 换明文 → 修改
ausPlain[] 数组,长度须为 16 的整数倍
- 改密钥长度 → 支持 192/256 位,修改
WIZ_AES_KEY_SIZE_128 为对应值
步骤2:CBC 模式加解密
CBC 模式需要额外的初始化向量(IV),每个明文块在加密前与前一个密文块异或。在 ECB 基础上设置 pu8IV 字段并将模式改为 CBC 即可。
/* CBC 加密 */
uint8_t ausIV[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10};
memset((uint8_t *)&callAes, 0, sizeof(callAes));
callAes.pu8In = ausPlain;
callAes.u32InLen = AES_TEST_LEN;
callAes.pu8Out = ausResult;
callAes.u32OutLen = AES_TEST_LEN;
callAes.pu8IV = ausIV;
callAes.pu8Key = ausKey;
callAes.ulOpt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_ENCRYPT | WIZ_AES_OPT_KEY_128;
callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYN_CRYPTO_CALL) - 4);
WIZAES_EncDec(&callAes);
printf("The AES (CBC) encrypted message is:\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
printf("%02x", ausResult[i]);
printf("\r\n");
/* CBC 解密 */
memset((uint8_t *)&callAes, 0, sizeof(callAes));
callAes.pu8In = ausResult;
callAes.u32InLen = AES_TEST_LEN;
callAes.pu8Out = ausPlain;
callAes.u32OutLen = AES_TEST_LEN;
callAes.pu8IV = ausIV;
callAes.pu8Key = ausKey;
callAes.ulOpt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_DECRYPT | WIZ_AES_OPT_KEY_128;
callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYN_CRYPTO_CALL) - 4);
WIZAES_EncDec(&callAes);
printf("The AES (CBC) decrypted message is:\r\n");
for (i = 0; i < AES_TEST_LEN; i++)
printf("%02x", ausPlain[i]);
printf("\r\n");
CBC 模式避免了相同明文块生成相同密文块的问题,安全性更高,是 TLS 通信中常用的模式。IV(初始化向量)用于第一个块的异或,后续块使用前一个密文块。
如果你想自定义
- 换 IV → 修改
ausIV[16] 数组,IV 不需要保密但每次加密应不同
- 切换 ECB/CBC → 修改
ulOpt 中的 WIZ_AES_OPT_BLK_ECB / WIZ_AES_OPT_BLK_CBC
编译与下载
Keil MDK 中打开 AES.uvprojx,F7 编译,确认 0 Error(s)。连接 DEBUG USB 口到 PC,F8 下载。下载成功后按 RESET 键启动新固件。
运行验证
打开 WIZ UartTool V1.0,选择开发板对应 COM 口,波特率 115200 / 8N1,打开串口。下载固件并按 RESET 后,串口会依次打印明文输入、密钥、ECB 加密结果、ECB 解密结果、CBC 加密结果、CBC 解密结果。
WIZ UartTool V1.0 显示 AES ECB/CBC 加密解密结果:明文、密文、解密后数据均为十六进制
常见问题
Q: 加密结果与 Python 等工具计算的结果不一致
确认密钥、IV、明文数据完全一致。注意 W55MH32L 使用 AES-128(16字节密钥),检查数据对齐和字节序。ECB 模式无需 IV,CBC 模式必须设置 IV。
Q: WIZAES_EncDec 调用后无输出
检查 callAes 结构体的 ui32Ctrl/ui32Crc 校验字段是否正确计算。该字段用于确保结构体数据完整性,校验不通过时硬件不会执行运算。
Q: 串口无任何输出
确认 COM 口号正确、波特率 115200,下载后需按 RESET 键启动。检查 printf 重定向的 fputc 函数是否正确实现。
总结
本文基于 W55MH32L 的硬件 AES-128 引擎实现了 ECB 和 CBC 两种模式的加密与解密:
- ECB 模式:每个 128 位块独立加密,简单快速,适合加密无结构的随机数据
- CBC 模式:每个明文块与前一个密文块异或后再加密,安全性更高,适合 TLS 通信和固件保护
- 通过
WIZ_SYN_CRYPTO_CAL_t 结构体配置密钥、IV、模式和操作类型,调用 WIZAES_EncDec() 执行硬件加速运算
- 硬件 AES 降低了 CPU 负担,具备恒定时延,适用于安全通信、固件加密、本地存储加密等场景