4. 设备身份初始化:预置密钥、设备序列号、信任锚的生成与安全存储

设备身份初始化,说白了就是给设备办一张「出生证明」。这张证明决定了设备以后能不能被信任、能不能安全地跟服务器通信。我见过太多项目,因为这一步没做好,后面整个安全体系都塌了。

咱们今天就把这件事拆开揉碎了讲。核心就三样东西:设备序列号、预置密钥、信任锚。这三者怎么生成、怎么存、怎么用,直接决定了设备的安全水位。

4.1 设备序列号:唯一身份标识

设备序列号(Serial Number, SN)是设备在物理世界里的身份证号。它必须唯一,而且不能被篡改。

4.1.1 序列号的生成策略

我个人习惯把序列号设计成三段式结构:

字段 长度 说明
厂商代码 4字节 标识制造商,比如 0x0001 代表某公司
产品型号 2字节 标识产品线或硬件版本
唯一序号 6字节 递增计数器或随机数,保证唯一性

这样设计的好处是:光看序列号就能知道设备是谁家的、什么型号、第几台。我在项目中遇到过,有些厂商直接用 MAC 地址当序列号,结果换网卡就得换身份,折腾死人。

注意:序列号一旦出厂就不能改。如果允许通过软件修改,那攻击者就能伪造身份,整个信任体系就崩了。

4.2 预置密钥:设备的初始密码

预置密钥(Pre-shared Key, PSK)是设备出厂时烧进去的对称密钥。它用来做设备注册时的身份凭证,或者直接用于通信加密。

4.2.1 密钥的生成方式

我建议用硬件真随机数生成器(TRNG)来生成密钥。伪随机数生成器(PRNG)在种子泄露时,所有密钥都能被推算出来——这个坑我踩过。

// 伪代码:安全生成预置密钥
uint8_t psk[32];
trng_generate_random(psk, 32);  // 从硬件 TRNG 获取 32 字节随机数

密钥长度至少 16 字节(128 位),我个人推荐 32 字节(256 位)。别为了省那几字节的存储空间,把安全底线给丢了。

4.2.2 密钥与序列号的绑定

光有密钥还不够,得把密钥和序列号绑在一起。常用的做法是:

  • 方法一:在安全芯片内部,用序列号作为索引,查找对应的密钥
  • 方法二:用序列号派生密钥:key = KDF(主密钥, 序列号)
  • 方法三:在服务器端维护一张 <序列号, 密钥> 映射表

方法二我最常用。它不需要在设备里存映射表,服务器只要知道主密钥和序列号,就能算出设备的预置密钥。

小技巧:派生时加上设备类型、批次号等上下文信息,可以防止跨型号的密钥碰撞。

4.3 信任锚:信任的起点

信任锚(Trust Anchor)是设备验证服务器身份、或者服务器验证设备证书的根凭据。它通常是一个根证书或者根公钥。

4.3.1 信任锚的生成

信任锚一般由设备制造商或平台运营方生成。我建议用离线方式生成,私钥永远不联网:

  1. 在离线环境中生成 RSA-2048 或 ECC P-256 密钥对
  2. 用私钥自签名生成根证书
  3. 将根证书(公钥部分)烧录到设备中
  4. 私钥保存在硬件安全模块(HSM)里,物理隔离

核心原则:信任锚的私钥一旦泄露,所有依赖这个信任锚的设备都得报废。所以私钥必须放在 HSM 里,连管理员都拿不到。

4.4 安全存储:把秘密锁进保险柜

生成完了,怎么存?存在 Flash 里?那跟把钥匙贴在门上没区别。

4.4.1 存储介质对比

存储方式 安全等级 成本 适用场景
普通 Flash 低 低 玩具级产品,不推荐
安全芯片(SE) 高 中 大多数 IoT 设备
TPM/TEE 高 中高 网关、边缘计算设备
HSM 极高 高 服务器端、CA 系统

我建议至少用安全芯片(SE)。普通 MCU 的 Flash 用 JTAG 或者漏洞就能把密钥读出来,我亲眼见过有人用逻辑分析仪就把 SPI Flash 里的密钥抓出来了。

4.4.2 安全芯片的操作流程

安全芯片的核心能力是:密钥可以进去,但永远出不来。操作流程一般是:

  1. 设备上电后,主控通过 I2C/SPI 向安全芯片发送指令
  2. 安全芯片在内部用预置密钥解密或签名
  3. 安全芯片只返回结果,不返回密钥本身
// 示例:安全芯片签名流程
// 主控发送待签名数据
se_write(&data, len);
// 安全芯片返回签名结果
se_read(signature, 64);
// 主控永远拿不到私钥
警告:别把密钥明文存在文件系统里。我曾经审计过一个项目,他们把预置密钥写在一个叫 key.txt 的文件里,还放在根目录——这跟没锁门有什么区别?

4.5 整体流程与架构

下面这张图展示了设备身份初始化的完整流程。从生成到存储,每一步都不能省。

设备身份初始化流程 设备身份初始化流程 阶段一:身份要素生成 设备序列号 三段式结构生成 预置密钥 TRNG 生成 32 字节 信任锚 离线生成根证书 阶段二:身份绑定 序列号 ↔ 密钥 映射关系建立 信任锚与设备身份关联 阶段三:安全存储 安全芯片(SE) TPM / TEE HSM(服务器端) 核心原则:私钥永不离开安全硬件,信任锚私钥离线保存在 HSM 中

4.6 避坑指南

做了这么多年安全,我总结了几条血泪教训:

  • 别用固定密钥:我曾经见过一个项目,一万台设备用同一个预置密钥。一台被破解,全部沦陷。
  • 别把密钥写死在代码里:反编译就能看到。应该从安全芯片里读,或者从 OTP 区域加载。
  • 别忽略物理攻击:攻击者可能用探针、激光、电压毛刺来读取密钥。安全芯片要有主动屏蔽层和电压检测。
  • 别忘记密钥轮换:预置密钥只是初始身份,注册后应该升级为会话密钥或证书。
我的建议:如果预算允许,直接用支持 ECC 的安全芯片。ECC 的密钥更短、性能更好,而且很多安全芯片原生支持 ECDSA 签名,能省不少开发时间。

嗯,设备身份初始化这块,说白了就是「生得好、存得牢、用得对」。生得好——用真随机数生成唯一序列号和密钥;存得牢——锁进安全芯片,谁也拿不走;用得对——注册后及时升级密钥。这三条做到了,设备身份安全就有了八成把握。