OTA 加密完整方案(嵌入式 IoT 常用)

OTA 安全分传输加密 、固件包本身加密(存储加密) 、**固件数字签名(验签,防篡改 / 伪造)**三块,很多人容易混淆:签名保证包是官方、没被改;加密保证别人截获后看不懂固件内容,两者必须搭配,不能只用一个。

推荐算法:

  • 固件内容加密:AES-GCM(AEAD,加密 + 完整性一体,首选),其次 AES-CCM;不要单独 AES-CBC/CTR(还要额外做 MAC,容易踩坑)
  • 签名验签:ECDSA P256(资源小,MCU 首选);大容量设备可用 RSA2048/RSA3072
  • 传输:HTTPS (TLS1.2/1.3)、MQTTs、CoAPs

一、两种加密维度

1)传输链路加密(网络传输时加密)

作用:固件在服务器→设备网络链路上,中间人抓包只能拿到密文。

  • 实现:直接用 TLS。HTTP→HTTPS,MQTT→MQTTs,CoAP→CoAPs
  • 优点:最简单,不需要改固件包格式,设备端只需要 mbedtls/tinycrypt
  • 局限:下载到设备本地 flash 的固件仍是明文;攻击者拿到 flash 可以直接 dump 固件逆向。

适合:只防网络抓包,不需要保护固件镜像本身。

2)固件镜像加密(包本身加密,重点)

目标:下载到设备 flash 里的 OTA 镜像也是密文,即使读出 flash 也看不到明文固件。

架构:非对称密钥分发 + 对称 AES 加密固件(标准做法,因为 AES 加密大固件速度快、开销低)

完整流程(服务器端打包)
  1. 生成一次性CEK(内容密钥,AES-128/256) ,随机生成,每个固件包用独立 CEK
  2. 使用 CEK + IV,用 AES-GCM 加密整个固件 bin,得到密文固件 + auth tag(校验标签)
  3. 用设备公钥(RSA/ECDH)加密这个 CEK,把【加密后的 CEK + IV + tag + 密文固件】打包成 OTA 包
  4. 再对整个固件元数据 / 固件哈希做数字签名(私钥签名),附加到包头部 /manifest 清单
设备端流程(Bootloader/APP 里执行)
  1. 下载完整 OTA 包,先验签 :用设备内置的公钥校验签名,签名失败直接丢弃,不做解密(防止耗算力的拒绝服务攻击)
  2. 验签通过后,取出加密的 CEK,用设备私钥解密得到 CEK
  3. 使用 CEK、IV,AES-GCM 解密密文固件,同时校验 auth tag;tag 错误 = 固件被篡改,拒绝升级
  4. 解密得到明文固件,写入运行分区;双分区 A/B 分区,启动校验失败可回滚

密钥存储重点:

  • 设备私钥 不能直接放在普通 flash,优先放安全芯片 SE/TEE/MCU eFuse;
  • 验签用的公钥可以烧录在固件 /efuse,公开不怕泄露;
  • 服务器签名私钥离线保管,HSM 硬件密码机保存,绝对不能放到 web 服务器。

二、极简选型对比

表格

方案 原理 优点 缺点 适用场景
仅 TLS 传输加密 HTTPS/MQTTs 实现最简单,不用改 bin 包 flash 里固件明文,可 dump 逆向 简单小设备,不担心固件被 dump
AES 对称预共享密钥 (PSK) 设备和服务器烧同一个 AES 密钥加密固件 运算快,代码量小 密钥泄露所有设备全部沦陷,密钥更新麻烦 封闭小批量项目,不推荐量产
AES-GCM + ECDH/RSA 密钥封装(推荐) AES 加密固件,非对称传递 AES 密钥 每个包 CEK 独立;密钥泄露影响范围小;AEAD 自带完整性 代码复杂,需要非对称密码库 量产 IoT,工业、车载 OTA

三、和 Secure Boot(安全启动)的关系

Secure Boot:Bootloader 只允许验签通过的固件运行,不负责加密;就算固件是明文,没有合法签名就拒绝启动。

  • 组合最佳实践:镜像 AES 加密 + Secure Boot 验签 + A/B 双分区 + 版本防回滚(anti-rollback,版本计数器)
  • ESP32 等芯片还有硬件 Flash 加密:固件写入 flash 时硬件自动加密,属于片内存储加密,和 OTA 镜像加密是两套东西。

四、开发落地要点

  1. 验签一定要在解密前面,不要先解密再验签,会存在拒绝服务、密码学攻击风险。
  2. AES-GCM 的 IV 必须随机、唯一,同一个 CEK 不能重复 IV;IV 明文随 OTA 包下发,不需要保密。
  3. A/B 双分区:新固件下载到备用分区,解密 + 验签全部通过后,才切换启动分区;启动失败自动回滚到老版本。
  4. 防回滚:存入安全存储的版本号计数器,不允许刷低于当前版本的固件,防止降级攻击。
  5. 密码库:mbedtls、tinycrypt、wolfssl;优先开启 MCU 硬件加密加速器(AES、SHA、ECC),降低 CPU 开销。

五、最简 OpenSSL 演示(服务器打包示意)

复制代码
# 1.生成AES256-GCM的CEK和IV
CEK=$(openssl rand -hex 32)
IV=$(openssl rand -hex 12)

# 2.AES-GCM加密固件bin,输出密文+tag
openssl enc -aes-256-gcm -K $CEK -iv $IV -in app.bin -out app_enc.bin -tag app.tag

# 3.用RSA公钥加密CEK,把加密后的CEK、IV、tag、密文打包进OTA头部
# 4.用RSA/ECDSA私钥对固件哈希签名,附加到包头部

设备端逆操作:验签 → RSA 解密取出 CEK → AES-GCM 解密并校验 tag。

六、常见坑

  1. 只做 SHA256 哈希校验,没有数字签名:攻击者可以替换固件,同时修改哈希值,完全绕过。
  2. 把签名和加密顺序搞反,先解密再验签。
  3. AES 复用 IV,直接破坏 AES-GCM 安全。
  4. 密钥明文放在固件 bin 里,一 dump 全部泄露。
  5. 没有 A/B 分区,升级中途断电直接变砖。
相关推荐
Nontee1 小时前
Quartz 新手入门:定时任务的两个承诺
开发语言·windows·python
\光辉岁月/2 小时前
2.异常类
java·开发语言·异常类
淡海水2 小时前
05-03-源码-Boehm GC分配与碎片管理
开发语言·算法·unity·c#·游戏引擎·gc
努力实干2 小时前
C++ 面向对象与工程架构
开发语言·c++·架构
十年Java程序媛2 小时前
JVM 基础与 GC 垃圾回收详解|可达性分析、分代模型、垃圾收集器、STW
java·开发语言·jvm·spring boot·后端·面试
估值探索者2 小时前
【Python量化选股流水线 #03】候选股怎么排序?动量+低波+流动性三因子打分取 Top-N
开发语言·python·接口·api接口·股票数据接口·数据接口·股票数据api接口
骑士雄师2 小时前
supervisor 中关于上下文多轮信息维护常用到的python语法
开发语言·python
曹牧2 小时前
C#:字符串占位符与值数量不一致
开发语言·数据库·c#
迅猛龙办公室2 小时前
Python函数实现反转一个只有3位数的整数
开发语言·前端·python