Appearance
威胁模型
如果你认为"只要用了HTTPS就安全了"或者"MQTT Broker的ACL就够了",那么这份文档就是为你准备的。
问题背景
在点对点通信中,当你收到一个数据包时:
- 如何确认它真的来自声称的发送者?
- 如何确认发送者有权限执行该操作?
- 如何防止消息被窃听或篡改?
常见的错误认知
| 错误认知 | 问题 |
|---|---|
| "MQTT ACL够用了" | ACL只控制谁能发布到哪个主题,不验证消息内容真实性 |
| "用了TLS就安全" | TLS只保护传输层,不支持蓝牙等非TCP传输 |
| "JWT可以解决一切" | 每条消息带JWT = 542字节开销,蓝牙场景不可接受 |
| "加密了就不会被篡改" | 大错特错! 加密≠认证,没有Tag的密文可以被精确修改 |
核心挑战
我们的场景
多个客户端(手机、门锁、服务器)需要互相通信,但:
客户端之间如何鉴别对方身份?
- 不能总是依赖中心服务器
- 蓝牙场景下完全离线
如何验证对方权限?
- 不能把权限写死在代码里
- 需要灵活管理
如何保护消息?
- 不能被窃听(机密性)
- 不能被篡改(完整性)
- 不能被重放(新鲜性)
传输方式的多样性
我们需要支持:
| 传输方式 | 特点 | TLS可用? |
|---|---|---|
| MQTT | 通过Broker中继 | ✅ 可以 |
| 蓝牙BLE | 真正的离线P2P | ❌ 不可以 |
| WiFi Direct | 局域网P2P | ❌ 一般不用 |
| 未来传输 | 未知 | ❌ 不确定 |
结论:不能依赖传输层安全(TLS),必须在应用层解决安全问题。
设计思路演进
尝试1:每条消息JWT签名
json
{
"payload": {...},
"jwt": "eyJhbGciOiJFZDI1NTE5..."
}问题:
- JWT太长(Header + Payload + Signature = 542字节)
- 即使用Ed25519签名也需86字节
- 蓝牙BLE的MTU仅23字节,完全不可接受
尝试2:对称密钥签名
客户端A和B共享同一个secret,用HMAC签名问题:
- 对称密钥意味着双方都能伪造对方的消息
- 一旦泄露,整个系统崩溃
- 无法区分谁发的消息
尝试3:mTLS客户端证书
每个设备有自己的X.509证书,TLS层验证身份问题:
- 依赖TLS层,蓝牙不可用
- 证书管理复杂
- 不满足"传输层无关"要求
最终方案:会话协商
借鉴HTTPS的思路:
- 握手阶段(可以大):交换身份凭证,协商密钥
- 通信阶段(必须小):用会话密钥加密+认证
关键安全原则
1. 自证明身份
Device ID = Base58(Ed25519公钥)
- 身份即公钥,无需第三方证明
- 能用私钥签名的,必定是该设备
- 借鉴:libp2p、IPFS
2. 身份与权限解耦
Credential证明"你是谁",权限表决定"你能做什么"
- Credential由认证服务器签发,永久有效
- 权限表存储在设备端,可随时更新
- 撤销用户?从权限表删除uid即可
3. 加密必须带认证
没有Tag的加密 = 没有锁的保险箱
ChaCha20等流加密的XOR特性导致:
python
# 攻击者截获密文(不知道密钥!)
ciphertext = intercept()
# 知道JSON格式,猜测 {"a":3} (查询)
# 想改成 {"a":1} (解锁)
# 直接修改密文
tampered[offset] ^= ord('3') ^ ord('1')
# 门锁解密 → 得到 {"a":1} → 门开了!必须使用AEAD(如ChaCha20-Poly1305):加密+认证一体化,任何篡改都会被检测。
4. 前向安全
每次会话使用临时密钥对:
- 会话结束后销毁临时密钥
- 即使长期私钥泄露,历史会话仍安全
- 借鉴:TLS 1.3、Signal Protocol
5. 纵深防御
不依赖单一防护层:
- 传输层:可选TLS(如果传输支持)
- 会话层:握手协商,身份验证
- 应用层:权限表,业务逻辑检查
为什么不能偷懒?
场景1:只加密不认证
"我用AES加密了,很安全吧?"
错! 攻击者可以:
- 位翻转攻击:不知道密钥也能精确修改消息
- 已知明文攻击:猜测格式后构造有效密文
- 结果:门锁在你不知情的情况下被打开
场景2:信任Broker ACL
"MQTT Broker的ACL控制了谁能发消息给我,够了吧?"
错! ACL无法:
- 验证消息内容是否被篡改
- 验证发送者的Ed25519签名
- 阻止Broker被入侵后的恶意消息
场景3:硬编码权限
"我在代码里写死了谁有什么权限,改不了。"
错! 会导致:
- 无法撤销权限(用户离职了怎么办?)
- 无法临时授权(朋友来访怎么办?)
- 固件更新才能改权限(不现实)
技术选型总结
| 组件 | 选择 | 原因 |
|---|---|---|
| 签名算法 | Ed25519 | 32字节公钥,64字节签名,安全高效 |
| 密钥交换 | X25519 ECDH | 前向安全,临时密钥协商 |
| 加密认证 | ChaCha20-Poly1305 | AEAD一体化,软件实现快,适合嵌入式 |
| 序列化 | CBOR | 二进制JSON,比JSON小50%+ |
| 编码 | Base58 | 无易混淆字符,适合手动输入 |
下一步
根据你的安全需求,选择合适的方案:
