找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2|回复: 0
收起左侧

ChaCha20 流密码在 Cortex-M0+上加密存储,700B Flash 即可

[复制链接]
ID:277903 发表于 2026-7-31 04:01 | 显示全部楼层 |阅读模式
PY32F002A 试用 ChaCha20 流密码加密 FlashStore 存储数据

ChaCha20 是什么
ChaCha20 是一种流密码(stream cipher),RFC 8439 标准。它是 TLS 1.3、QUIC、WireGuard 等新一代协议的默认加密算法之一,Google 在移动端全面用它替代 AES。和 AES 不同,它不需要硬件加速器,纯软件就能在 MCU 上高效运行。

核心特性:

  • 对称加密:加密和解密是同一个操作(XOR 密钥流),调用同一个函数
  • 无对齐要求:数据不需要 4 字节对齐,任意长度都能处理
  • 资源友好:Cortex-M0+ 上 -Os 编译仅占约 700 字节 Flash,约 200 字节栈
  • 输入参数:32 字节密钥 + 12 字节 nonce(同一密钥下 nonce 不能重复)


在 PY32F002A 上的用法
结合之前移植的 FlashStore A/B 分区存储,把 ChaCha20 作为加密层叠加在上面:
  1. 保存: 明文 → ChaCha20 加密 → FlashStore_Save → 写入 Flash
  2. 加载: FlashStore_Load → 密文 → ChaCha20 解密 → 明文
复制代码
核心代码三行:
  1. chacha20_crypt(data, size, key, nonce); // 加密(或解密,同一函数)
  2. FlashStore_Save(&cfg, data, size); // 存到闪存
  3. FlashStore_Load(&cfg, data, size); // 读回
  4. chacha20_crypt(data, size, key, nonce); // 解密
复制代码


实测:加密一句名言
用 "Stay hungry, stay foolish." 做测试,32 字节密钥 + 12 字节 nonce。

明文:
  1. 53 74 61 79 20 68 75 6e 67 72 79 2c 20 73 74 61 │Stay hungry, sta
  2. 79 20 66 6f 6f 6c 69 73 68 2e 00 00 00 00 00 00 │y foolish.......
复制代码
加密后 — 完全不可读:
  1. 3a 28 1d a0 11 62 cd 14 4a 03 07 03 93 67 63 73 │:(...b..J....gcs
  2. 69 d1 59 2f a1 dd 95 06 2d 14 b5 28 29 ee 9f 0a │i.Y/....-..()...
复制代码
FlashStore 存盘再读回,解密还原 — 一字不差。



资源占用
PY32F002A(Cortex-M0+,48MHz,-Os):

模块Flash说明
flash_store594 BA/B 分区核心
flash_store_port230 BHAL 适配
chacha20~700 B加密/解密
合计~1.5 KB含加密的可靠闪存存储
如果只需要存储不需要加密,去掉 ChaCha20 即可,约 800 字节搞定。



完整源码
只有 100 行,零依赖,复制到任何 MCU 项目即可使用。
  1. #include "chacha20.h"
  2. #include <string.h>

  3. #define QR(a, b, c, d) do { \
  4.     (a) += (b); (d) ^= (a); \
  5.     (d) = ((d) << 16) | ((d) >> 16); \
  6.     (c) += (d); (b) ^= (c); \
  7.     (b) = ((b) << 12) | ((b) >> 20); \
  8.     (a) += (b); (d) ^= (a); \
  9.     (d) = ((d) << 8) | ((d) >> 24); \
  10.     (c) += (d); (b) ^= (c); \
  11.     (b) = ((b) << 7) | ((b) >> 25); \
  12. } while (0)

  13. static uint32_t ld32(const uint8_t *p) {
  14.     uint32_t v;
  15.     memcpy(&v, p, sizeof(v));
  16.     return v;
  17. }

  18. static void st32(uint8_t *p, uint32_t v) {
  19.     memcpy(p, &v, sizeof(v));
  20. }

  21. static void chacha20_block(uint8_t out[​64​], const uint32_t init[​16​]) {
  22.     uint32_t x[​16​];
  23.     memcpy(x, init, sizeof(x));

  24.     for (int i = 0; i < 10; i++) {
  25.         QR(x[​0​], x[​4​], x[​ 8​], x[​12​]);
  26.         QR(x[​1​], x[​5​], x[​ 9​], x[​13​]);
  27.         QR(x[​2​], x[​6​], x[​10​], x[​14​]);
  28.         QR(x[​3​], x[​7​], x[​11​], x[​15​]);
  29.         QR(x[​0​], x[​5​], x[​10​], x[​15​]);
  30.         QR(x[​1​], x[​6​], x[​11​], x[​12​]);
  31.         QR(x[​2​], x[​7​], x[​ 8​], x[​13​]);
  32.         QR(x[​3​], x[​4​], x[​ 9​], x[​14​]);
  33.     }

  34.     for (int i = 0; i < 16; i++)
  35.         st32(out + i * 4, x[​i​] + init[​i​]);
  36. }

  37. void chacha20_crypt(uint8_t *data, size_t size,
  38.                     const uint8_t key[​32​], const uint8_t nonce[​12​]) {
  39.     if (size == 0) return;

  40.     uint32_t state[​16​];
  41.     state[​0​] = 0x61707865u;
  42.     state[​1​] = 0x3320646eu;
  43.     state[​2​] = 0x79622d32u;
  44.     state[​3​] = 0x6b206574u;

  45.     for (int i = 0; i < 8; i++)
  46.         state[​4 + i​] = ld32(key + i * 4);

  47.     state[​12​] = 1;

  48.     for (int i = 0; i < 3; i++)
  49.         state[​13 + i​] = ld32(nonce + i * 4);

  50.     uint8_t keystream[​64​];
  51.     size_t offset = 0;

  52.     while (offset < size) {
  53.         chacha20_block(keystream, state);

  54.         size_t chunk = size - offset;
  55.         if (chunk > 64) chunk = 64;

  56.         for (size_t i = 0; i < chunk; i++)
  57.             data[​offset + i​] ^= keystream[​i​];

  58.         offset += chunk;
  59.         state[​12​]++;
  60.     }
  61. }
复制代码
头文件:
  1. #ifndef CHACHA20_H
  2. #define CHACHA20_H

  3. #include <stddef.h>
  4. #include <stdint.h>

  5. void chacha20_crypt(uint8_t *data, size_t size,
  6.                     const uint8_t key[​32​], const uint8_t nonce[​12​]);

  7. #endif
复制代码



build 31 July 2026 03:59 (UTC+8)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表