4、加密传输通道:TLS/DTLS协议在资源受限设备上的裁剪,预共享密钥(PSK)模式,端到端加密
好,咱们进入第四讲。这一讲,我打算聊聊加密传输通道。
你想想看,助听器固件升级,说白了就是把新代码从手机App或者云端,一路送到助听器芯片里。这条路要是没加密,就等于在明信片上写银行卡密码。谁都能看,谁都能改。
我在早期的一个项目里,就吃过这个亏。当时为了赶工期,用了最简单的HTTP下载,结果测试阶段就发现,固件包在传输过程中被人篡改了。虽然只是内部测试,但那个教训让我记到现在。从那以后,我对传输通道的加密,就再也不敢马虎了。
4.1 为什么是TLS/DTLS?
很多人会问:助听器这么小的设备,跑得动TLS吗?
我的回答是:跑得动,但得会“裁剪”。
标准的TLS握手,需要证书交换、非对称加密、随机数生成……这些操作对PC来说小菜一碟,但对只有几十KB RAM、几MHz主频的助听器芯片来说,那就是一场噩梦。
所以,我们得用DTLS。DTLS是TLS的“UDP版本”,它解决了TLS依赖TCP的问题。助听器经常处于低功耗状态,连接不稳定,用UDP更合适。DTLS在UDP上实现了类似TLS的安全层,握手更轻量,重传机制也更适合无线环境。
我个人习惯,在助听器OTA场景里,优先选DTLS 1.2。为什么?因为1.3虽然更新,但很多芯片的加密加速器还不支持。1.2的生态最成熟,裁剪起来也最顺手。
4.2 预共享密钥(PSK)模式
说到裁剪,最核心的一刀,就是砍掉证书交换,改用PSK模式。
PSK,预共享密钥。说白了,就是助听器和手机App在出厂时,就约定好一个秘密。这个秘密只有他俩知道。握手时,不需要CA证书,不需要RSA签名,直接拿这个密钥来验证身份、生成会话密钥。
这样做的好处很明显:
- 握手速度快:少了证书验证,握手从几百毫秒降到几十毫秒。
- 代码体积小:不需要解析X.509证书,不需要实现RSA或ECC的签名验证,固件能省下好几KB。
- 功耗低:计算量小了,电池自然更耐用。
但PSK也有代价。最大的问题就是:密钥怎么分发?
我在项目中遇到过最头疼的事,就是密钥写死在固件里,结果固件被逆向,密钥泄露,整个产品线的设备都成了“裸奔”。
所以,我建议的做法是:
- 每台设备独立密钥:出厂时,根据设备唯一ID(比如蓝牙MAC或芯片序列号),结合一个主密钥,派生出每个设备的PSK。
- 密钥存储安全:PSK必须存储在芯片的安全区(如TrustZone或独立的SE),不能明文暴露在Flash里。
- 定期轮换:每次OTA成功后,可以协商一个新的PSK,用于下一次升级。
重要提醒:PSK模式虽然轻量,但它的安全性完全依赖于密钥的保密性。一旦密钥泄露,整个安全体系就崩塌了。所以,密钥的生命周期管理,是PSK模式的重中之重。
4.3 端到端加密:不只是传输层
很多人以为,用了TLS/DTLS,数据就安全了。其实不然。
TLS/DTLS只保护了“传输通道”。如果云端服务器被攻破,或者手机App被植入恶意代码,那么数据在到达助听器之前,就已经被泄露了。
端到端加密,就是要解决这个问题。它的核心思想是:数据在发送端加密,只有接收端能解密,中间任何节点(包括服务器)都看不到明文。
在助听器OTA场景里,我通常这样设计:
- 固件包在云端存储时就是加密的:云端只负责存储和转发,它没有解密密钥。
- 手机App只做中继:App从云端下载加密的固件包,然后通过蓝牙传给助听器。App本身不解密。
- 助听器芯片内完成解密:助听器收到加密包后,用自己存储的私钥(或派生密钥)进行解密,然后校验签名,最后才写入Flash。
这样做的好处是:即使云端被黑,或者手机被Root,攻击者拿到的也只是一堆密文,毫无用处。
我的小技巧:端到端加密的密钥,可以和PSK分开。PSK用于建立DTLS通道,而端到端加密的密钥,可以是一个独立的对称密钥,或者用设备的公钥加密一个会话密钥。这样即使PSK泄露,攻击者也只能看到传输内容,但无法解密固件包本身。
4.4 裁剪实战:DTLS 1.2 + PSK 的最小实现
嗯,这里要注意,裁剪不是乱砍。你得知道哪些功能可以砍,哪些必须留。
我列一个我常用的裁剪清单:
| 功能模块 | 裁剪建议 | 理由 |
|---|---|---|
| 证书验证 | 完全移除 | PSK模式下不需要 |
| 非对称加密(RSA/ECC) | 完全移除 | PSK模式下不需要 |
| 随机数生成 | 保留,但简化 | 用于生成握手随机数和会话密钥 |
| 密码套件 | 只保留TLS_PSK_WITH_AES_128_CCM | AES-CCM在资源受限设备上性能好,且支持硬件加速 |
| 会话恢复 | 移除 | OTA场景每次都是新连接,不需要恢复 |
| 扩展字段 | 只保留必要的(如SNI) | 减少解析开销 |
经过这样的裁剪,DTLS 1.2 + PSK的代码体积,可以从标准的几十KB,压缩到5KB以内。RAM占用也能控制在1KB左右。这对于助听器芯片来说,完全是可以接受的。
我曾经在一个Cortex-M0+的芯片上,跑过这样的裁剪版DTLS。握手时间大约30ms,每次传输的加密开销不到5ms。嗯,效果还不错。
4.5 避坑指南
最后,分享几个我踩过的坑:
我曾经……在PSK的派生上犯过错误。当时为了省事,直接用设备MAC地址作为PSK。结果发现,蓝牙广播里MAC地址是明文的,攻击者只要抓个包,就能拿到PSK。后来我改用HMAC-SHA256,用主密钥对MAC地址做一次哈希,才解决了这个问题。
还有一点:不要忽略重放攻击。DTLS本身有防重放机制,但如果你裁剪得太狠,把这个功能也砍了,那就危险了。攻击者可以截获一个合法的固件包,然后反复发送,导致助听器反复升级,耗尽电池。所以,我建议在固件包里加入一个单调递增的序列号,助听器每次升级后记录这个序列号,拒绝重复的包。
好了,这一讲就到这里。加密传输通道,说白了就是给固件包穿上一件防弹衣。PSK模式是轻量化的关键,端到端加密是最后一道防线。下一讲,我们会聊聊固件包的签名和校验,那是确保固件“身份真实”的关键一步。