全部例程

AES-ECB_CBC硬件加密功能

W55MH32

更新于 2026年8月27日

本篇总结

使用硬件 AES-128,实现 ECB/CBC 模式的加解密验证。配套 CRYPT 例程同时覆盖 DES、TDES、SHA、SM1、SM3、SM4、SM7 等密码算法。

🔑 KEIL MDK、UART调试、AES、CRYPT

硬件平台:本例程基于 W55MH32L-EVB 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W55MH32L-EVB

W55MH32 集成了硬件 AES-128 加密引擎,支持 ECB(电子密码本)和 CBC(密码块链接)两种工作模式。本示例演示如何使用硬件 AES 对 64 字节明文进行 ECB/CBC 加密并解密验证。配套的 CRYPT 例程还包含 DES、TDES、SHA-160/224/256、SM1、SM3、SM4、SM7 等算法的自测,串口会逐项输出 Pass/Fail 结果。

前置工具准备

开始本例程前,请确认以下工具已安装:

硬件连接

本例程无需外部硬件连接,AES 运算完全在芯片内部完成。USART1 的 TX(PA9) 和 RX(PA10) 通过板载 USB 转串口芯片连接到 DEBUG USB 口,用于输出加密解密结果。

引脚功能方向模式
PA9USART1_TX开发板 → PC复用推挽输出 (AF_PP)
PA10USART1_RXPC → 开发板浮空输入 (IN_FLOATING)

工程结构

工程位于 SDK 内 1.SDK\ModuleDemo\CRYPT\,核心文件如下:

CRYPT/
├── Project/
│   └── MDK-ARM(uV4)/          ← Keil 工程文件
└── User/
    ├── main.c                 ← 串口初始化 + printf 重定向 + 测试入口
    ├── define.h               ← 通用宏定义
    ├── w55mh32_conf.h         ← 外设头文件集中包含
    ├── w55mh32_it.c/h         ← 中断服务函数
    └── cryptlibTest/          ← 各算法自测文件
        ├── aes_self_test.c    ← AES-128 ECB/CBC 加解密
        ├── des_self_test.c    ← DES + TDES ECB/CBC
        ├── sha_self_test.c    ← SHA-160/224/256
        ├── sm1_self_test.c    ← SM1 ECB (128/192/256)
        ├── sm3_self_test.c    ← SM3 
        ├── sm4_self_test.c    ← SM4 ECB/CBC
        ├── sm7_self_test.c    ← SM7 ECB/CBC
        ├── debug.c/h          ← r_printf / ouputRes 辅助函数
        ├── wiz_bignum_tool.c/h← 大数运算工具
        └── wiz_cephes.c/h     ← 数学运算库

步骤1:AES 结构体与 ECB 加解密

文件:User/cryptlibTest/aes_self_test.c | 函数:AES_Func_Test() — 定义 64 字节明文、密钥、预存期望密文,填充 WIZ_SYM_CRYPT_CALL 结构体后调用 WIZAES_EncDec() 执行 ECB 加密,将结果与预存密文比对判定 Pass/Fail;再用密文作为输入执行解密,与原始明文比对验证。

#define AES_TEST_LEN (64)

void AES_Func_Test() {
    uint8_t au8Plain[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,
        0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
        0x39,0x3A,0x3b,0x3c,0x3d,0x3e,0x3f,0x40};
    /* 预存 ECB 期望密文(用于结果校验) */
    uint8_t au8AESCipher_ECB[AES_TEST_LEN] = {
        0x34,0xC3,0x3B,0x7F,0x14,0xFD,0x53,0xDC,
        0xEA,0x25,0xE0,0x1A,0x02,0xE1,0x67,0x27,
        /* ... 共 64 字节 ... */
        0xA9,0x05,0x0C,0x10,0xCE,0x19,0x04,0xE7,
        0x50,0x59,0x77,0x97,0xA1,0x72,0xB0,0xF0};
    uint8_t au8Result[AES_TEST_LEN] = {0};
    uint8_t au8PN[AES_TEST_LEN] = {0};
    uint8_t au8Key[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
        0x09,0x0A,0x0b,0x0c,0x0d,0x0e,0x0f,0x10};
    WIZ_SYM_CRYPT_CALL callAes;

    /* ECB 加密 */
    memset((uint8_t *)&callAes, 0, sizeof(callAes));
    callAes.pu8In     = au8Plain;
    callAes.u32InLen  = AES_TEST_LEN;
    callAes.pu8Out    = au8Result;
    callAes.u32OutLen = AES_TEST_LEN;
    callAes.pu8Key    = au8Key;
    callAes.u16Opt = WIZ_AES_OPT_BLK_ECB | WIZ_AES_OPT_MODE_ENCRYPT | WIZ_AES_OPT_KEY_128;
    callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYM_CRYPT_CALL) - 4);
    WIZAES_EncDec(&callAes);
    r_printf((0 == memcmp(au8AESCipher_ECB, au8Result, AES_TEST_LEN)),
             "wiz_aes_128_ecb ENC test\n");

    /* ECB 解密 */
    memset((uint8_t *)&callAes, 0, sizeof(callAes));
    callAes.pu8In     = au8Result;
    callAes.u32InLen  = AES_TEST_LEN;
    callAes.pu8Out    = au8PN;
    callAes.u32OutLen = AES_TEST_LEN;
    callAes.pu8Key    = au8Key;
    callAes.u16Opt = WIZ_AES_OPT_BLK_ECB | WIZ_AES_OPT_MODE_DECRYPT | WIZ_AES_OPT_KEY_128;
    callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYM_CRYPT_CALL) - 4);
    WIZAES_EncDec(&callAes);
    r_printf((0 == memcmp(au8Plain, au8PN, AES_TEST_LEN)),
             "wiz_aes_128_ecb DEC test\n");
}
  

ECB 模式中每个 128 位块独立加密,结构简单速度快。通过 u16Opt 字段选择工作模式(ECB)和操作类型(加密/解密),通过 WIZ_AES_OPT_KEY_128 指定密钥长度。u32Crc 字段由 WIZCRC_CalcBuff() 计算校验值,确保结构体数据完整性。加密结果通过 memcmp 与预存期望密文比对,由 r_printf() 输出 Pass 或 Fail。

如果你想自定义

  • 换密钥 → 修改 au8Key[16] 数组内容
  • 换明文 → 修改 au8Plain[] 数组,长度须为 16 的整数倍
  • 改密钥长度 → 支持 192/256 位,修改 WIZ_AES_OPT_KEY_128 为对应值

步骤2:CBC 模式加解密

CBC 模式需要额外的初始化向量(IV),每个明文块在加密前与前一个密文块异或。在 ECB 基础上设置 pu8IV 字段并将模式改为 CBC 即可。

    uint8_t au8Iv[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
        0x09,0x0A,0x0b,0x0c,0x0d,0x0e,0x0f,0x10};
    /* 预存 CBC 期望密文(用于结果校验) */
    uint8_t au8AESCipher_CBC[AES_TEST_LEN] = {
        0xDB,0xF1,0x84,0x11,0x2E,0xB9,0x11,0x16,
        0x59,0x71,0x2B,0xAF,0xCF,0xF2,0xAB,0x24,
        /* ... 共 64 字节 ... */
        0x1D,0x4F,0xB5,0x05,0xB9,0xF4,0x24,0xEF,0xB9};

    /* CBC 加密 */
    memset((uint8_t *)&callAes, 0, sizeof(callAes));
    callAes.pu8In     = au8Plain;
    callAes.u32InLen  = AES_TEST_LEN;
    callAes.pu8Out    = au8Result;
    callAes.u32OutLen = AES_TEST_LEN;
    callAes.pu8IV     = au8Iv;
    callAes.pu8Key    = au8Key;
    callAes.u16Opt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_ENCRYPT | WIZ_AES_OPT_KEY_128;
    callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYM_CRYPT_CALL) - 4);
    WIZAES_EncDec(&callAes);
    r_printf((0 == memcmp(au8AESCipher_CBC, au8Result, AES_TEST_LEN)),
             "wiz_aes_128_cbc ENC test\n");

    /* CBC 解密 */
    memset((uint8_t *)&callAes, 0, sizeof(callAes));
    callAes.pu8In     = au8AESCipher_CBC;
    callAes.u32InLen  = AES_TEST_LEN;
    callAes.pu8Out    = au8Result;
    callAes.u32OutLen = AES_TEST_LEN;
    callAes.pu8IV     = au8Iv;
    callAes.pu8Key    = au8Key;
    callAes.u16Opt = WIZ_AES_OPT_BLK_CBC | WIZ_AES_OPT_MODE_DECRYPT | WIZ_AES_OPT_KEY_128;
    callAes.u32Crc = WIZCRC_CalcBuff(0xffff, &callAes, sizeof(WIZ_SYM_CRYPT_CALL) - 4);
    WIZAES_EncDec(&callAes);
    r_printf((0 == memcmp(au8Plain, au8Result, AES_TEST_LEN)),
             "wiz_aes_128_cbc DEC test\n");
  

CBC 模式避免了相同明文块生成相同密文块的问题,安全性更高,是 TLS 通信中常用的模式。IV(初始化向量)用于第一个块的异或,后续块使用前一个密文块。

如果你想自定义

  • 换 IV → 修改 au8Iv[16] 数组,IV 不需要保密但每次加密应不同
  • 切换 ECB/CBC → 修改 u16Opt 中的 WIZ_AES_OPT_BLK_ECB / WIZ_AES_OPT_BLK_CBC

运行验证

打开 WIZ UartTool V1.0,选择开发板对应 COM 口,波特率 115200 / 8N1,打开串口。下载固件并按 RESET 后,串口会依次打印明文输入、密钥、ECB 加密结果、ECB 解密结果、CBC 加密结果、CBC 解密结果。

AES-128 ECB/CBC 内置密文与加密后密文验证的 Pass/Fail 结果

常见问题

Q: 加密结果与 Python 等工具计算的结果不一致

确认密钥、IV、明文数据完全一致。注意 W55MH32 使用 AES-128(16字节密钥),检查数据对齐和字节序。ECB 模式无需 IV,CBC 模式必须设置 IV。

Q: WIZAES_EncDec 调用后无输出

检查 callAes 结构体的 u32Crc 校验字段是否正确计算。该字段由 WIZCRC_CalcBuff() 生成,用于确保结构体数据完整性,校验不通过时硬件不会执行运算。

Q: 串口无任何输出

确认 COM 口号正确、波特率 115200,下载后需按 RESET 键启动。检查 printf 重定向的 fputc 函数是否正确实现。

Q: 某项测试输出 Fail 后程序卡死

这是正常行为。r_printf() 在检测到结果不匹配时会输出 Fail 并进入 while(1) 死循环,防止错误级联。检查对应算法的密钥、明文、期望密文是否一致后重新编译下载。

总结

本文基于 W55MH32 的硬件 AES-128 引擎实现了 ECB 和 CBC 两种模式的加密与解密验证:

  • ECB 模式:每个 128 位块独立加密,简单快速,适合加密无结构的随机数据
  • CBC 模式:每个明文块与前一个密文块异或后再加密,安全性更高,适合 TLS 通信和固件保护
  • 通过 WIZ_SYM_CRYPT_CALL 结构体配置密钥、IV、模式和操作类型,调用 WIZAES_EncDec() 执行硬件加速运算,结果与预存期望值比对判定 Pass/Fail
  • 配套 CRYPT 例程还覆盖了 DES/TDES、SHA-160/224/256、SM1、SM3、SM4、SM7 等多种密码算法,硬件加速降低了 CPU 负担,具备恒定时延,适用于安全通信、固件加密、本地存储加密等场景

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5 配套开发板

Andy

W5500 技术支持专家