3、设备身份认证:设备唯一标识、证书签发流程、双向认证机制设计

设备身份认证,说白了就是解决一个问题——我怎么知道跟我说话的这盏灯,真的是它自己,而不是别人冒充的?

我在智能照明项目里踩过这个坑。早期我们用的方案很简单,每个设备烧录一个固定密码。结果呢?生产线上有人把密码泄露了,整个小区的灯都被别人控制了。嗯,从那以后,我再也不敢用这种「裸奔」方案了。

3.1 设备唯一标识:给每盏灯一个「身份证」

设备唯一标识,是认证的根基。你想想看,如果连唯一性都保证不了,后面的认证全是白搭。

我个人习惯用这三类标识:

  • 硬件级标识:比如MCU的芯片唯一ID(UID),或者Wi-Fi模块的MAC地址。这东西出厂就烧死了,改不了。
  • 产线级标识:生产时写入的序列号(SN),通常包含批次、日期、型号信息。我建议SN长度至少16字节,避免碰撞。
  • 密钥级标识:设备证书中的CN(Common Name)字段,或者预置的Device ID。这个跟后面的证书体系挂钩。

重要提醒:千万别只用MAC地址当唯一标识。我在项目中遇到过,MAC地址可以被伪造,而且同一型号的模组MAC可能重复(别问我怎么知道的)。正确的做法是:MAC + 芯片UID + 产线随机数,三者拼接成一个全局唯一的Device ID。

举个例子,我们当时设计的Device ID格式是这样的:

// 设备唯一标识结构
typedef struct {
    uint8_t  chip_id[8];      // 芯片UID,从寄存器读取
    uint8_t  mac_addr[6];     // Wi-Fi/BLE MAC地址
    uint32_t factory_sn;      // 产线序列号,递增
    uint8_t  reserved[2];     // 保留位,用于扩展
} device_id_t;

// 实际生成逻辑
void generate_device_id(uint8_t *out_id, uint32_t id_len) {
    // 读取芯片UID
    read_chip_uid(out_id);
    // 拼接MAC
    memcpy(out_id + 8, get_mac_addr(), 6);
    // 写入产线SN
    uint32_t sn = get_factory_sn();
    memcpy(out_id + 14, &sn, 4);
    // 最后做一次SHA256哈希,得到最终标识
    sha256(out_id, 18, out_id);
}

3.2 证书签发流程:从「裸奔」到「持证上岗」

有了唯一标识,接下来就是给它发「证书」。说白了,证书就是一张数字身份证,里面写着「我是谁,谁给我担保的,我的公钥是什么」。

我建议采用三级CA架构:

层级 名称 作用 安全要求
Root CA 根证书 整个体系的信任锚点 离线存储,物理隔离
Intermediate CA 中间证书 签发设备证书,分担风险 产线专用,定期轮换
Device Cert 设备证书 每个设备独有,用于认证 私钥不可导出

具体的签发流程,我习惯分五步走:

  1. 生成密钥对:设备在产线上首次上电时,内部生成RSA-2048或ECC-P256密钥对。私钥永远不出芯片,只存公钥。
  2. 创建CSR:设备用私钥签名一个证书签名请求(CSR),里面包含Device ID和公钥。
  3. 产线签名:产线服务器验证CSR签名后,用Intermediate CA的私钥签发设备证书。证书有效期我建议设2年,到期OTA更新。
  4. 证书注入:将签好的证书写回设备的Flash或安全元件中。同时,设备需要预置Intermediate CA证书用于验证。
  5. 产线自检:设备用证书和私钥做一次本地签名验证,确保证书和私钥匹配。这一步很多人跳过,但我建议一定要做。

我的小技巧:产线签发时,可以在证书的Subject字段里嵌入设备的生产批次号和经纬度信息。这样后期如果发现某批次设备有问题,可以直接通过证书吊销列表(CRL)批量撤销,不用一台台找。

3.3 双向认证机制设计:你信我,我也信你

单向认证,说白了就是设备验证服务器的身份。但智能照明场景下,服务器也得验证设备的身份——不然谁都能连上来发指令,那不乱套了?

双向认证,就是双方互相验明正身。我常用的流程是这样的:

// 双向认证流程(简化版)
1. 设备连接服务器,发起TLS握手
2. 服务器发送自己的证书(Server Cert)
3. 设备验证服务器证书:
   - 检查证书链是否完整
   - 检查证书是否在有效期内
   - 检查证书是否被吊销(CRL/OCSP)
4. 设备发送自己的证书(Device Cert)
5. 服务器验证设备证书:
   - 同样检查证书链、有效期、吊销状态
   - 额外检查Device ID是否在白名单中
6. 双方协商会话密钥,建立加密通道

这里有个关键点——证书吊销检查。我在项目中遇到过,某批次设备证书泄露了,但因为没有及时吊销,攻击者拿着泄露的证书冒充了十几个设备。后来我们加上了OCSP Stapling,每次握手都实时检查证书状态。

注意:物联网设备资源有限,OCSP实时查询可能超时。我建议采用OCSP Stapling + 本地CRL缓存的双重方案。服务器定期推送CRL到设备,设备本地缓存,握手时优先查本地,查不到再走OCSP。

另外,双向认证的握手开销确实不小。对于资源受限的Zigbee或BLE Mesh设备,我建议改用PSK(预共享密钥)方式:

  • 设备出厂时,烧录一个唯一的PSK(基于Device ID派生)
  • 服务器端也保存同样的PSK
  • 握手时,双方通过PSK生成会话密钥,省去证书交换的步骤

但PSK有个缺点——如果服务器被攻破,所有设备的PSK都会泄露。所以我的建议是:关键设备(如网关、主控)用证书双向认证,普通终端设备用PSK。这样既保证了安全性,又兼顾了性能。

3.4 避坑指南:我踩过的那些坑

做设备身份认证这几年,我总结了几条血泪教训:

  • 别把私钥放在固件里:我曾经见过有人把私钥硬编码在代码里,结果固件被反编译,整个产品线的设备都废了。私钥必须放在安全元件(SE)或TEE中。
  • 证书有效期别设太长:我建议设备证书最长2年,中间证书最长5年。到期必须OTA更新,否则设备变「孤儿」。
  • 产线安全要重视:产线上下载私钥的电脑,必须离线操作。我见过产线工人用U盘拷私钥,结果U盘丢了...嗯,那场面。
  • 别忘了做兼容性测试:不同厂家的TLS库实现有差异。我遇到过某款芯片的mbedTLS不支持ECC证书,折腾了两天才发现。

好了,设备身份认证这块,核心就是「唯一标识 + 证书体系 + 双向验证」。说白了,就是让每盏灯都有一张独一无二的身份证,而且每次见面都要互相亮证。做到这三点,你的智能照明系统在身份认证这块,基本就稳了。