4. DTLS在CoAP中的角色:DTLS如何保护CoAP、安全模式对比
好,咱们进入第4章。这一章我打算把DTLS在CoAP里的位置彻底讲透。很多初学者容易把CoAP和DTLS割裂开看,觉得DTLS就是个“加个锁”的步骤。其实不是这样。DTLS和CoAP的关系,更像是信封和信纸——没有信封,信纸上的内容谁都能看。
我在做智能照明项目时,就遇到过客户问:“CoAP本身不是有重传机制吗?为什么还要DTLS?”嗯,这个问题问到了点子上。CoAP的重传只保证消息到达,不保证消息不被篡改或偷看。说白了,CoAP管“能不能送到”,DTLS管“送的是不是原样、有没有被偷看”。
4.1 DTLS在CoAP协议栈中的位置
先看一张图,你就明白DTLS插在哪儿了。
你看,DTLS 夹在 CoAP 和 UDP 之间。这意味着什么?CoAP 把消息交给 DTLS,DTLS 加密后再交给 UDP 发送。反过来,UDP 收到数据先交给 DTLS 解密,验证通过后才交给 CoAP 处理。
我个人习惯把 DTLS 比作一个安检通道。CoAP 消息进去之前是明文,出来之后就是密文。接收端那边,密文进去,验证通过后还原成明文。整个过程对 CoAP 上层是透明的——你写 CoAP 代码时根本感觉不到 DTLS 的存在。
4.2 DTLS 如何保护 CoAP 消息
DTLS 给 CoAP 提供了三层保护,我一个个说。
4.2.1 机密性(Confidentiality)
说白了就是加密。CoAP 的请求和响应内容,比如温度传感器的读数、开关指令,在网络上传输时都是密文。我在做智能门锁项目时,曾经抓包看过未加密的 CoAP 消息——开门指令的 URI 路径和 payload 清清楚楚。如果被中间人截获,直接就能开门。加了 DTLS 后,抓包看到的全是乱码。
4.2.2 完整性(Integrity)
保证消息在传输过程中没有被篡改。DTLS 会给每条消息附加一个消息认证码(MAC)。接收端收到后重新计算 MAC,如果对不上,说明消息被改过,直接丢弃。我曾经在测试环境中故意修改了一个 DTLS 加密包的一个字节,结果接收端直接报错,不会把篡改后的数据交给 CoAP。
4.2.3 身份认证(Authentication)
确认通信双方的身份。DTLS 握手阶段会交换证书或预共享密钥,确保你连接的是真正的服务器,而不是伪装的中间人。这一点在固件升级场景特别重要——你肯定不希望设备从恶意服务器下载带后门的固件。
4.3 四种安全模式对比
CoAP 规范(RFC 7252)定义了四种安全模式。我整理了一张表,方便你对比。
| 安全模式 | 认证方式 | 密钥管理 | 计算开销 | 适用场景 |
|---|---|---|---|---|
| NoSec | 无 | 无 | 无 | 内网调试、非敏感数据 |
| PreSharedKey | 预共享密钥 | 手动配置 | 低 | 资源受限设备、小规模部署 |
| RawPublicKey | 非对称密钥对 | 公钥指纹交换 | 中 | 中等规模、无PKI基础设施 |
| Certificate | X.509证书链 | CA签发 | 高 | 大规模部署、需要可扩展性 |
4.3.1 NoSec 模式
这个模式其实就是裸奔。CoAP 直接跑在 UDP 上,没有任何安全保护。我建议只在以下情况使用:
- 本地局域网调试,抓包分析协议行为
- 传感器数据不敏感,比如室内温度采集
- 网络环境完全可控,比如设备间通过有线连接
但要注意,生产环境千万别用 NoSec。我在一个客户现场见过他们把智能电表的数据用 NoSec 传到公网服务器,结果被第三方抓包看到了用电规律——这其实已经涉及隐私泄露了。
4.3.2 PreSharedKey(PSK)模式
PSK 模式使用对称密钥。通信双方预先配置好相同的密钥,DTLS 握手时用这个密钥进行身份认证和生成会话密钥。
优点很明显:计算开销小,适合单片机、Zigbee 模块这类资源受限设备。缺点也很突出:密钥分发困难。你想想看,如果有 1000 台设备,每台都要手动烧录密钥,生产管理就是个噩梦。
PSK 模式的 DTLS 握手流程大致如下:
Client Hello ——> 包含PSK身份提示
<—— Server Hello + ServerKeyExchange
ClientKeyExchange ——> 包含PSK身份
<—— ChangeCipherSpec + Finished
ChangeCipherSpec ——>
Finished ——>
[加密通信开始]
4.3.3 RawPublicKey(RPK)模式
RPK 模式使用非对称密钥对。每个设备有自己的公钥和私钥,通信时交换公钥(或者公钥的哈希值)进行认证。
相比 PSK,RPK 的好处是不需要预先共享密钥,密钥管理更灵活。但计算开销比 PSK 大,因为涉及非对称加密运算。我记得在 ARM Cortex-M4 上做 RPK 握手,一次完整的 ECDHE 密钥交换大概需要几百毫秒——对于实时性要求高的场景,这个延迟需要考虑。
RPK 的典型配置方式:
// 生成密钥对(以mbedTLS为例)
mbedtls_pk_context key;
mbedtls_pk_init(&key);
mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1,
mbedtls_pk_ec(key),
mbedtls_ctr_drbg_random,
&ctr_drbg);
// 提取公钥指纹(SHA-256哈希)
uint8_t fingerprint[32];
mbedtls_sha256(public_key_der, public_key_len, fingerprint, 0);
4.3.4 Certificate 模式
这是最完整的 DTLS 安全模式。使用X.509 证书链进行身份认证,证书由证书颁发机构(CA)签发。
Certificate 模式的优势在于可扩展性。新设备加入网络时,只要持有 CA 签发的证书,就能自动完成认证。不需要像 PSK 那样手动配置密钥,也不需要像 RPK 那样交换公钥指纹。
但代价也很明显:
- 证书管理需要 PKI 基础设施
- 握手过程更复杂,需要验证证书链
- 内存占用大,证书和私钥可能占用几十 KB
我在一个智慧城市项目中部署了 Certificate 模式,管理 10 万+ 设备。说实话,前期搭建 CA 和证书签发系统花了不少功夫,但后期设备入网完全是自动化的,省了很多运维成本。
4.4 如何选择安全模式
我一般按照这个思路来选择:
- 先问自己:数据敏感吗? 不敏感且在内网,NoSec 就够了。
- 设备资源够吗? 内存小于 64KB、CPU 主频低于 100MHz,优先考虑 PSK。
- 设备数量多少? 少于 100 台,PSK 或 RPK 都行;超过 1000 台,建议上 Certificate。
- 有没有 PKI 基础设施? 没有的话,RPK 是 Certificate 的轻量替代方案。