4. 固件加密传输:TLS/DTLS协议、密钥协商、会话管理
固件升级最怕什么?我最怕的就是固件在传输过程中被人篡改。你想想看,辛辛苦苦编译好的固件,在空中被人换成了恶意版本,那后果不堪设想。所以,加密传输这道防线,必须扎牢。
这一章,我们就来聊聊固件加密传输的核心:TLS/DTLS协议怎么选、密钥怎么安全地协商、会话怎么管。嗯,这里要注意,很多工程师只关注加密算法,却忽略了握手和会话管理的细节,结果反而出了大漏洞。
4.1 传输层协议选型:TLS vs DTLS
先解决一个基础问题:用TLS还是DTLS?
我个人习惯这样判断:如果设备跑的是TCP/IP协议栈,固件升级走HTTP或MQTT over TCP,那就用TLS。如果设备用的是UDP,比如CoAP协议,那就得用DTLS。
| 特性 | TLS (1.2/1.3) | DTLS (1.2/1.3) |
|---|---|---|
| 底层传输 | TCP(可靠、有序) | UDP(不可靠、无序) |
| 握手开销 | 2-RTT (TLS 1.3为1-RTT) | 3-RTT(需处理丢包重传) |
| 适用场景 | Wi-Fi、以太网设备 | LoRa、NB-IoT、Zigbee等低功耗无线 |
| 固件大小影响 | 较大(完整TLS栈约50-100KB) | 较小(DTLS精简实现可到20KB) |
| 抗重放攻击 | 天然支持(TCP序列号) | 需额外实现(epoch + sequence_number) |
4.2 密钥协商:不只是握手那么简单
密钥协商,说白了就是让设备和服务器在不安全的信道上,安全地商量出一个只有他俩知道的密钥。TLS握手协议干的就是这个活。
但嵌入式环境有它的特殊性。我遇到过一个问题:设备第一次上电,没有预置任何证书,怎么和服务器建立信任?
4.2.1 预置信任锚
最稳妥的做法,是在工厂烧录时就把服务器的根证书或公钥写进设备的信任存储区。这样设备在握手时就能验证服务器证书的合法性。
- 证书链验证: 设备收到服务器证书后,逐级向上验证,直到信任锚。注意,一定要校验证书有效期和吊销状态。
- 公钥固定(Public Key Pinning): 直接存储服务器公钥的哈希值。握手时比对服务器证书中的公钥哈希是否匹配。这个方法省资源,但更换服务器密钥时需要同步更新设备。
4.2.2 预共享密钥(PSK)模式
对于资源极度受限的设备,TLS PSK模式是个好选择。它不需要证书,只需要设备和服务器预先共享一个对称密钥。
// TLS 1.3 PSK 握手简化流程(客户端侧)
1. 设备从NVM中读取PSK ID和PSK值
2. 构造ClientHello,携带PSK key_share
3. 服务器验证PSK ID,返回ServerHello + 加密的扩展
4. 双方直接计算主密钥,无需证书交换
5. 握手完成,开始加密传输
// 注意:PSK需要定期轮换,建议每次固件升级成功后更新PSK
嗯,这里要注意,PSK虽然轻量,但密钥管理是难点。如果所有设备都用同一个PSK,一台被破解,全网沦陷。所以,我建议每台设备使用唯一的PSK,并在服务器端做好密钥生命周期管理。
4.3 会话管理:别让握手拖慢升级
固件升级通常需要传输大量数据。如果每次连接都重新握手,那开销太大了。会话管理就是为了解决这个问题。
4.3.1 会话复用(Session Resumption)
TLS 1.2支持会话ID和会话票证(Session Ticket)两种复用方式。TLS 1.3则统一使用PSK-based会话复用。
| 复用方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 会话ID | 服务器缓存会话状态,客户端携带ID恢复 | 实现简单 | 服务器有状态,负载高 |
| 会话票证 | 服务器加密会话状态发给客户端,客户端下次携带 | 服务器无状态,可扩展 | 票证加密密钥需妥善管理 |
| TLS 1.3 PSK复用 | 握手时直接使用PSK派生密钥 | 0-RTT,延迟最低 | 存在重放攻击风险(需额外防护) |
4.3.2 会话超时与清理
会话不能无限期有效。我一般这样设置:
- 会话超时: 24小时。超过这个时间,强制重新握手。
- 最大复用次数: 10次。防止会话被无限重用,降低密钥暴露风险。
- 密钥更新: 每次固件升级完成后,触发一次密钥更新(Key Update),生成新的会话密钥。
4.4 核心流程:固件加密传输全链路
说了这么多,我们来画一张图,把整个流程串起来。这张图是我在项目中实际使用的架构,经过多次迭代优化。
4.5 避坑指南与性能优化
最后,分享几个我在实战中总结的经验,希望能帮你少走弯路。
我曾经接手过一个项目,设备使用自签名证书,但代码里没有做任何公钥固定。结果中间人攻击轻松得手。正确的做法是:要么使用CA签发的证书,要么做公钥固定(HPKP)。
TLS 1.2支持False Start,允许客户端在握手未完全完成时就发送应用数据。对于固件升级这种大文件传输,这个优化能减少一个RTT的延迟。实测下来,在4G网络下能节省约100ms。
嵌入式设备的网络环境往往不稳定。我建议将TLS记录大小设置为1400字节(适应以太网MTU),并启用TCP_NODELAY。这样可以避免IP分片,减少重传概率。在弱网环境下,这个调整能让传输成功率提升30%以上。
嗯,关于固件加密传输,核心就是三件事:选对协议(TLS/DTLS)、安全地协商密钥、高效地管理会话。把这三点做好,你的固件升级通道就基本安全了。记住,安全是一个持续的过程,不是一次性的配置。定期审计、及时更新,才能让你的设备始终处于安全状态。