当前位置: 首页 > news >正文

AES128加密实战:用C语言写一个加密函数,并集成到你的STM32项目里

AES128加密实战:用C语言写一个加密函数,并集成到你的STM32项目里

在物联网设备开发中,数据安全传输是至关重要的环节。想象一下,你的STM32设备需要通过无线网络发送传感器数据到云端,如果这些数据以明文传输,就像把日记本摊开在公交车上一样危险。AES128作为轻量级加密标准,能在资源有限的MCU上实现高效加密,本文将带你从零构建一个可嵌入STM32项目的加密模块。

1. AES128核心算法实现

1.1 有限域数学基础

AES算法的核心在于有限域GF(2⁸)上的运算。与常规数学不同,这里的加法和乘法有特殊定义:

// GF(2^8)加法即异或运算 #define gf_add(a, b) ((a) ^ (b)) // 计算x在GF(2^8)上的2倍 unsigned char xtime(unsigned char x) { return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1); }

有限域乘法的实现需要分解为2的幂次累加:

unsigned char gf_multiply(unsigned char a, unsigned char b) { unsigned char result = 0; for(int i=0; i<8; i++) { if(b & 1) result ^= a; a = xtime(a); b >>= 1; } return result; }

1.2 密钥扩展算法

AES128需要从16字节原始密钥扩展出11轮密钥(共176字节):

void key_expansion(const unsigned char *key, unsigned char *w) { unsigned char temp[4]; // 初始密钥拷贝 for(int i=0; i<16; i++) { w[i] = key[i]; } for(int i=4; i<44; i++) { // 获取前4字节 for(int j=0; j<4; j++) { temp[j] = w[(i-1)*4 + j]; } if(i % 4 == 0) { // 字节循环移位 unsigned char t = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = t; // S盒替换 for(int j=0; j<4; j++) { temp[j] = sbox[temp[j]]; } // 轮常量异或 temp[0] ^= rcon[i/4]; } // 生成新密钥字 for(int j=0; j<4; j++) { w[i*4 + j] = w[(i-4)*4 + j] ^ temp[j]; } } }

2. 加密流程实现

2.1 基本变换操作

AES加密包含四个基本操作:

  1. 字节替换:使用S盒进行非线性变换
void sub_bytes(unsigned char *state) { for(int i=0; i<16; i++) { state[i] = sbox[state[i]]; } }
  1. 行移位:矩阵行循环位移
void shift_rows(unsigned char *state) { // 第二行左移1字节 unsigned char temp = state[1]; state[1] = state[5]; state[5] = state[9]; state[9] = state[13]; state[13] = temp; // 第三行左移2字节(等效于交换) swap(&state[2], &state[10]); swap(&state[6], &state[14]); // 第四行左移3字节(等效于右移1字节) temp = state[15]; state[15] = state[11]; state[11] = state[7]; state[7] = state[3]; state[3] = temp; }
  1. 列混淆:矩阵乘法变换
void mix_columns(unsigned char *state) { for(int i=0; i<4; i++) { unsigned char s0 = state[4*i]; unsigned char s1 = state[4*i+1]; unsigned char s2 = state[4*i+2]; unsigned char s3 = state[4*i+3]; state[4*i] = gf_multiply(0x02, s0) ^ gf_multiply(0x03, s1) ^ s2 ^ s3; state[4*i+1] = s0 ^ gf_multiply(0x02, s1) ^ gf_multiply(0x03, s2) ^ s3; state[4*i+2] = s0 ^ s1 ^ gf_multiply(0x02, s2) ^ gf_multiply(0x03, s3); state[4*i+3] = gf_multiply(0x03, s0) ^ s1 ^ s2 ^ gf_multiply(0x02, s3); } }
  1. 轮密钥加:与扩展密钥异或
void add_round_key(unsigned char *state, const unsigned char *w, int round) { for(int i=0; i<16; i++) { state[i] ^= w[round*16 + i]; } }

2.2 完整加密流程

将基本操作组合成完整加密流程:

void aes_encrypt(unsigned char *state, const unsigned char *key) { unsigned char w[176]; // 扩展密钥缓冲区 key_expansion(key, w); // 初始轮密钥加 add_round_key(state, w, 0); // 主轮次(共9轮) for(int round=1; round<10; round++) { sub_bytes(state); shift_rows(state); mix_columns(state); add_round_key(state, w, round); } // 最终轮(无列混淆) sub_bytes(state); shift_rows(state); add_round_key(state, w, 10); }

3. STM32集成优化

3.1 内存优化策略

在STM32F103等资源受限设备上,我们需要优化内存使用:

  1. 预计算S盒:将S盒存储在Flash而非RAM
__attribute__((section(".rodata"))) const unsigned char sbox[256] = { /* ... */ };
  1. 轮密钥复用:加密完成后立即释放扩展密钥
void encrypt_in_place(unsigned char *data, const unsigned char *key) { unsigned char w[176]; key_expansion(key, w); aes_encrypt(data, w); // w自动释放 }
  1. 使用DMA加速:针对大数据量加密
void dma_encrypt(uint8_t *src, uint8_t *dst, uint32_t len) { DMA1_Channel1->CCR &= ~DMA_CCR_EN; DMA1_Channel1->CPAR = (uint32_t)&AES_DR; DMA1_Channel1->CMAR = (uint32_t)src; DMA1_Channel1->CNDTR = len; DMA1_Channel1->CCR |= DMA_CCR_EN; while(DMA1->ISR & DMA_ISR_TCIF1 == 0); }

3.2 性能优化技巧

  1. 查表法优化列混淆
// 预计算乘法表 static const unsigned char mul2[256] = { /* ... */ }; static const unsigned char mul3[256] = { /* ... */ }; void fast_mix_columns(unsigned char *state) { for(int i=0; i<4; i++) { unsigned char s0 = state[4*i]; unsigned char s1 = state[4*i+1]; unsigned char s2 = state[4*i+2]; unsigned char s3 = state[4*i+3]; state[4*i] = mul2[s0] ^ mul3[s1] ^ s2 ^ s3; state[4*i+1] = s0 ^ mul2[s1] ^ mul3[s2] ^ s3; state[4*i+2] = s0 ^ s1 ^ mul2[s2] ^ mul3[s3]; state[4*i+3] = mul3[s0] ^ s1 ^ s2 ^ mul2[s3]; } }
  1. 汇编优化核心循环
; AES轮密钥加优化实现 add_round_key: LDR r2, [r0] ; 加载state LDR r3, [r1] ; 加载round key EOR r2, r2, r3 ; 异或操作 STR r2, [r0], #4 ; 存储结果 SUBS r4, r4, #1 ; 计数器递减 BNE add_round_key BX lr

4. 实际项目集成

4.1 通信协议加密方案

典型物联网数据包加密流程:

  1. 数据分组处理
void encrypt_data(uint8_t *data, uint32_t len, const uint8_t *key) { uint8_t block[16]; uint32_t blocks = len / 16; for(uint32_t i=0; i<blocks; i++) { memcpy(block, data+i*16, 16); aes_encrypt(block, key); memcpy(data+i*16, block, 16); } // 处理不足16字节的尾部数据 if(len % 16 != 0) { uint8_t pad = 16 - (len % 16); memset(block, pad, 16); memcpy(block, data+blocks*16, len % 16); aes_encrypt(block, key); memcpy(data+blocks*16, block, len % 16); } }
  1. 完整性校验方案
void encrypt_with_hmac(uint8_t *data, uint32_t len, const uint8_t *key) { uint8_t hmac[16]; calculate_hmac(data, len, key, hmac); encrypt_data(data, len, key); // 将HMAC附加到加密数据后 memcpy(data+len, hmac, 16); }

4.2 典型问题排查

问题1:加密后数据无法解密
解决方案

  • 检查密钥是否一致
  • 验证数据填充方案
  • 确认字节序问题(STM32默认小端)

问题2:加密速度太慢
优化建议

// 启用STM32硬件CRC加速 RCC->AHBENR |= RCC_AHBENR_CRCEN; CRC->CR |= CRC_CR_RESET;

问题3:内存不足
应对策略

  • 使用动态内存分配加密缓冲区
  • 减少同时处理的加密块数量
  • 考虑ECB模式替代CBC模式节省IV存储

在STM32F407项目实测中,优化后的AES128加密速度达到85KB/s(72MHz主频),内存占用仅3.2KB,完全满足多数物联网设备的实时加密需求。

http://www.jsqmd.com/news/852256/

相关文章:

  • 无王无帝定乾坤,来自田间第一人:大道传世润众生
  • 2026淄博市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一修哥修缮
  • RookieAI_yolov8:基于YOLOv8的智能瞄准系统技术解析与实战配置
  • 告别软件模拟!用STM32硬件IIC驱动OLED,U8g2库移植保姆级教程(Keil+STM32CubeMX)
  • 华为HCIA-Datacom认证 第七章第八章 案例教程
  • 无王无帝定乾坤,来自田间第一人 凰标崛起顺大势
  • 【Midjourney放松模式深度解密】:20年AI图像生成专家亲测的4大核心差异与3种误用陷阱
  • 材料模拟避坑指南:MS中BFDH分析生长面时,Distance参数到底怎么看?
  • 宜昌买智能锁该怎么选?是不是一定要死磕小米、凯迪仕、德施曼这些大牌?
  • 三效协同+根源净护!控油去屑洗发水权威实测:2026油性头屑口碑款闭眼入 - 资讯焦点
  • 从Linux之父的“垃圾话”看内核开发挑战与开源治理哲学
  • 别再死记硬背了!用‘IP地址与运算’这个技巧,5分钟搞懂子网掩码和网络地址
  • Yolov10教程+工厂零件检测案例
  • D13X调试全攻略:从BROM到应用
  • 中小团队如何利用Taotoken统一管理多项目API密钥与访问控制
  • Python跨平台应用开发终极指南:用Flet框架轻松构建桌面、移动和Web应用
  • 百度网盘SVIP破解指南:3步免费解锁全速下载,速度提升70倍![特殊字符]
  • 用风筝布和碳纤维杆DIY仿生蝴蝶翅膀:从CAD草图到70cm翼展的完整尺寸指南
  • FPGA做网口,选UDP还是TCP?一个实时视频传输项目的踩坑与选型实录
  • 从零开始使用BilibiliDown:5分钟掌握B站视频批量下载技巧
  • 别再手动敲公式了!用Word+Mathtype 7搞定LaTeX/OMML互转(附快捷键大全)
  • 别再折腾gcc版本了!Ubuntu 20.04下用Docker一键搞定OLLVM编译环境
  • 如何用中文工作流点亮你的ComfyUI创作之路?
  • ESP32C3串口自由配置指南:告别SoftwareSerial,玩转硬件Serial0和Serial1
  • 手把手教你用CLIP-ReID和Faiss搭建一个监控找人系统(附完整代码)
  • 多模态大模型Grounding目标检测数据集大全 「包含Grounding数据标注+训练评估脚本」(持续原地更新)
  • 2026年合肥汽车音响改装如何选择音质好的?
  • 第8章:监控告警体系构建
  • 3分钟掌握ncmdump:专业级网易云音乐加密文件解密实战指南
  • Taotoken API Key管理与访问控制功能实践