1. TLS 协议概述:从握手到加密,嵌入式安全的第一课
说实话,我第一次接触 TLS 是在一个智能门锁项目上。客户要求设备与手机 App 之间的通信必须加密,我当时第一反应是:「直接 AES 加密不就行了?」后来被安全审计打回来三次,才老老实实把 TLS 加上去。嗯,从那以后我就明白了——TLS 不是可选项,而是嵌入式联网设备的标配。
什么是 TLS?
TLS(Transport Layer Security,传输层安全协议)说白了,就是给网络通信加了一把「锁」。它工作在传输层之上,应用层之下。你想想看,你的设备通过 Wi-Fi 或蜂窝网络发送数据时,中间可能经过路由器、基站、云服务器……任何一个节点都能偷看甚至篡改你的数据。TLS 就是用来解决这个问题的。
它主要做三件事:
- 身份认证——确认你正在通信的对方确实是它声称的身份,而不是中间人
- 数据加密——通信内容只有收发双方能看懂,中间节点看到的全是乱码
- 完整性校验——数据在传输过程中有没有被篡改,一验就知道
核心要点:TLS 不是一种加密算法,而是一套协议框架。它组合了证书、非对称加密、对称加密、哈希算法等多种技术,形成一个完整的通信安全解决方案。
TLS 与 SSL 的关系
很多初学者会问:「TLS 和 SSL 有什么区别?」我简单说一下。
SSL(Secure Sockets Layer)是 TLS 的前身,由 Netscape 公司在 1990 年代开发。SSL 1.0 从未公开发布,SSL 2.0 在 1995 年发布,但很快被发现存在严重安全漏洞。SSL 3.0 在 1996 年发布,算是第一个真正可用的版本。
后来 IETF 接手了这个协议,把它改名为 TLS。TLS 1.0 实际上就是 SSL 3.0 的升级版。所以你可以理解为:TLS = SSL 的继任者。
| 版本 | 发布年份 | 状态 | 说明 |
|---|---|---|---|
| SSL 2.0 | 1995 | 已废弃 | 存在严重安全漏洞,不应使用 |
| SSL 3.0 | 1996 | 已废弃 | POODLE 攻击后于 2015 年废弃 |
| TLS 1.0 | 1999 | 已废弃 | 基于 SSL 3.0,但做了大量改进 |
| TLS 1.1 | 2006 | 已废弃 | 增加了对 CBC 攻击的防护 |
| TLS 1.2 | 2008 | 广泛使用 | 当前嵌入式设备的主流选择 |
| TLS 1.3 | 2018 | 推荐使用 | 握手更快、安全性更高 |
注意:我曾经在一个项目中看到有人为了兼容旧设备,启用了 SSL 3.0。结果安全扫描直接亮红灯。现在主流浏览器和云服务都已经强制要求 TLS 1.2 以上。嵌入式设备如果还在用 SSL 或 TLS 1.0/1.1,基本等于裸奔。
TLS 在嵌入式系统中的重要性
你可能会想:「我的设备就是个温度传感器,谁没事来攻击我?」
我以前也这么觉得,直到有一次帮客户排查问题——他们的一批智能电表在部署后频繁掉线,后来发现是有人在中继节点上注入了伪造的断电指令。如果当时用了 TLS,这种攻击根本不可能成功。
嵌入式系统面临的安全威胁其实更严峻:
- 物理可访问——设备可能部署在户外,攻击者可以直接接入网络接口
- 资源受限——CPU 主频低、内存小,跑不了复杂的加密算法
- 生命周期长——设备可能运行 5-10 年,协议版本必须能平滑升级
- 固件更新困难——一旦发现漏洞,OTA 升级可能受带宽限制
所以,在嵌入式系统里部署 TLS,不是「要不要」的问题,而是「怎么在有限资源下跑起来」的问题。这也是这门课的核心——我会带你一步步把 TLS 塞进你的 MCU 里。
TLS 协议栈架构
理解 TLS 的架构,是后续所有章节的基础。我习惯把它分成四层来看:
从上往下看:
- 应用层——你的业务数据在这里。HTTP、MQTT、CoAP 等协议都可以跑在 TLS 之上
- TLS 握手协议——建立连接时的「自我介绍」阶段。双方交换证书、协商加密算法、生成会话密钥。我习惯把它比作「第一次见面时互相验明正身」
- TLS 记录协议——握手完成后,真正的数据传输阶段。数据被分片、加密、加上 MAC 校验,然后交给下层发送
- 密码学原语层——TLS 不自己实现加密算法,而是调用底层的密码学库。常见的包括 OpenSSL、mbedTLS、WolfSSL 等
- 传输层——TCP 或 UDP。标准 TLS 跑在 TCP 上,DTLS 跑在 UDP 上
我的经验:在嵌入式系统里,握手协议是最耗时的环节。一次完整的 TLS 1.2 握手可能需要几百毫秒甚至几秒,取决于 CPU 性能和证书链长度。TLS 1.3 把握手从 2-RTT 降到了 1-RTT,对资源受限设备来说简直是福音。后面我会专门讲怎么优化握手性能。
嵌入式 TLS 的选型考量
选 TLS 实现库的时候,我一般会看这几个维度:
| 考量维度 | 说明 | 常见选择 |
|---|---|---|
| 代码体积 | Flash 占用是否在可接受范围内 | mbedTLS (~60KB)、WolfSSL (~40KB) |
| 内存占用 | RAM 峰值是否超过 MCU 限制 | mbedTLS 可配置到 ~10KB RAM |
| 算法支持 | 是否支持 ECC、TLS 1.3 | WolfSSL 对 ECC 支持较好 |
| 证书管理 | 是否支持证书链验证、CRL/OCSP | mbedTLS 内置 X.509 解析 |
| 许可证 | 商业项目是否合规 | mbedTLS (Apache 2.0)、WolfSSL (GPL/商业) |
我个人习惯在资源极度受限的设备上先用 WolfSSL,因为它裁剪起来更灵活。如果 Flash 和 RAM 相对宽裕,mbedTLS 的生态更成熟,文档也更全。后面我会专门用一章来对比这些库的移植过程。
避坑提醒:我曾经在一个项目里直接用了 OpenSSL 的全功能版本,结果编译出来 2MB+,MCU 的 Flash 才 1MB。后来换成 mbedTLS 并裁剪掉不需要的算法,最终只用了 80KB。记住:嵌入式 TLS 的第一原则是「只取所需」。