示例把 WireGuard 私钥放进一个字符数组,隧道就能工作,这正是这个问题反复出现的原因。你真正要做的决定不是「这安全吗」,而是「三个条件里哪一条适用于这次部署」。三个条件是:谁能物理接触到设备、在你这块板子上读 flash 能拿到什么、整批设备是共用一把密钥还是各带一把。回答完这三条,设计自然就定了,因为每一条改变的是密钥泄露后的代价,而不是它会不会泄露。

密钥授予了什么

WireGuard 用公钥认证对端。服务器把每个对端的公钥映射到一个地址和一份 AllowedIPs 列表,因此正是私钥让客户端能够以该地址作为源地址发送流量。

同一条记录也决定设备能访问哪些目标,所以密钥一旦泄露,暴露的不只是隧道地址,还有隧道后面的网络。

条件一:谁能拿到设备

如果设备锁在机柜里,团队之外没人碰它,风险主要是固件分发的问题。如果它发给客户、装在车里,或者因保修被退回,那么物理持有本身就是凭证,二进制是否保密反而是次要的。拿着设备的人根本不需要读密钥,因为正在运行的固件会替他打开隧道。所以服务器侧的答案必须包含吊销和有限的生命周期,而不只是把镜像保护起来。

先定这一条,再定另外两条,因为它决定了两者各自能拿到多少预算。

条件二:读 flash 能得到什么

任何能读取 flash 镜像的人都能还原以字面量形式存放的密钥,无论通过调试接口、升级包、备份还是退回的设备。 Flash 加密 提高了直接导出的成本,ESP-IDF 文档也说明了该特性在特定芯片和配置下覆盖什么。它并不能让密钥在任何攻击模型下都无法提取,对「设备就在手里」这种情况更是毫无作用。把它当成一层改变成本的手段,而不是答案。

在设计评审里断言某个属性之前,先读你所用芯片和配置的平台文档。

条件三:整批设备是否复用

一次量产共用一把密钥,意味着每台设备共享同一个身份。服务器在日志里区分不了它们,无法只吊销其中一台而不吊销全部,也分不清克隆机和原装机。按设备发密钥能把这三件事一起解决,代价是多一道注册流程,以及一份序列号到公钥的映射。这份映射才是把吊销变成改一行配置、而不是整批重刷的资产。

如果整批就是工作台上的五台,共用一把密钥也许是合理的取舍。如果是现场五百台,那就根本谈不上取舍。

让按设备发密钥真正可行的注册流程

首次启动时在设备上生成密钥对,私钥一半放进受保护的非易失存储,只把公钥发给注册服务,由它分配地址并写入对端记录。要对注册响应做认证,否则本地网络里的攻击者就能把自己的密钥注册到你的账号下。配网过程中绝不要把私钥打印到串口控制台。把设备序列号和公钥记在一起,这样丢了一台就能精确定位到一条对端记录。

这只是个小服务,但它决定了你拥有的是可审计的一批设备,还是只能整批重刷的一批设备。

时间、端点与决策

示例在启动隧道前同步时间,这件事的意义不止于 TLS:WireGuard 握手带有时间戳用于防重放,所以时钟错误的设备可能被拒绝握手。端点是主机名,这就把 DNS 放进了信任路径,尽管服务器的公钥仍然在认证对端。地址写错会浪费尝试次数,还会暴露设备何时在线。把这两件事处理好,再去争论密钥的问题。

然后再决定:只有在物理持有受控、批量也小的时候才用共享密钥;两者中任何一条不再成立,就改成按设备发密钥。

相关文章