4、轻量级认证协议设计:基于预共享密钥的认证、基于证书的认证、基于物理不可克隆函数的认证

好,咱们进入正题。NB-IoT 终端认证,说白了就是解决一个问题:「你是谁?你凭什么说你是你?」

在物联网场景下,终端设备资源受限,网络带宽窄,功耗要求高。传统的 HTTPS 双向认证、复杂的 PKI 体系,在 NB-IoT 上跑不动。所以,轻量级认证协议就成了关键。

我个人习惯把认证方案分成三类:基于预共享密钥(PSK)基于证书(Cert)基于物理不可克隆函数(PUF)。这三类各有各的脾气,咱们一个一个聊。

4.1 基于预共享密钥的认证

这是最朴素、最直接的方式。说白了,就是设备和服务器之间提前约定好一个密钥。认证时,设备用这个密钥证明身份。

核心流程:

  1. 设备出厂时,烧录一个唯一的 PSK 到安全存储区。
  2. 设备发起认证请求,携带设备 ID。
  3. 服务器生成一个随机数(Nonce),发给设备。
  4. 设备用 PSK 对 Nonce 做 HMAC 计算,返回结果。
  5. 服务器用同样的 PSK 计算 HMAC,比对结果。一致则通过。

关键点:PSK 必须安全存储。一旦泄露,整个认证体系就崩了。

我在项目中遇到过一个问题:某厂商的 NB-IoT 水表,PSK 直接明文存储在 Flash 里。结果呢?通过调试接口就能读出来。嗯,这其实是个低级错误,但现实中很常见。

代码示例(伪代码):

// 设备端
uint8_t psk[16] = {0x01, 0x02, ...}; // 预共享密钥
uint8_t nonce[8];                     // 服务器下发的随机数
uint8_t hmac_result[32];

hmac_sha256(psk, sizeof(psk), nonce, sizeof(nonce), hmac_result);
send_to_server(device_id, hmac_result);

// 服务器端
uint8_t expected_hmac[32];
hmac_sha256(stored_psk, sizeof(stored_psk), nonce, sizeof(nonce), expected_hmac);
if (memcmp(received_hmac, expected_hmac, 32) == 0) {
    // 认证通过
}

避坑指南:我曾经见过有人直接用 PSK 加密数据,而不是做 HMAC。这不对。HMAC 是「证明我知道密钥」,而不是「用密钥加密」。两者有本质区别。

优点:实现简单,计算量小,适合资源极度受限的终端。

缺点:密钥管理困难。设备多了,每个设备都要预置不同的 PSK,服务器要维护庞大的密钥表。而且,PSK 一旦泄露,无法远程更新。

4.2 基于证书的认证

证书认证,说白了就是「我有个身份证,上面有 CA 的签名」。你信不过我没关系,你信 CA 就行。

在 NB-IoT 场景下,我们通常用 轻量级 X.509 证书,或者干脆用 IEEE 802.1AR 的 IDevID 证书。证书里包含设备的公钥、设备 ID、CA 签名等信息。

核心流程:

  1. 设备出厂时,预置设备证书和 CA 根证书。
  2. 设备发起认证请求,发送设备证书。
  3. 服务器验证证书链(设备证书 → CA 证书),确认证书有效。
  4. 服务器生成随机数,用设备证书中的公钥加密后发给设备。
  5. 设备用私钥解密,返回解密后的随机数。
  6. 服务器比对随机数,一致则通过。

注意:证书认证的核心是「私钥安全」。私钥一旦泄露,证书就废了。必须把私钥放在安全芯片或 TEE 里。

我记得有一次,客户问能不能把私钥放在普通 Flash 里,用软件加密一下就行。我直接说不行。你想想看,软件加密的密钥本身也在 Flash 里,这跟把钥匙放在门垫下面有什么区别?

优点:可扩展性好。证书可以吊销、更新,适合大规模部署。

缺点:证书解析和验证需要较多计算资源。NB-IoT 终端通常只有几十 KB 的 RAM,解析一个完整的 X.509 证书可能很吃力。所以,我建议用 DER 格式,别用 PEM,能省不少空间。

对比项PSK证书
计算开销低(HMAC)中(非对称加解密)
存储开销低(16-32 字节)高(几百字节到几 KB)
密钥管理困难容易(CA 统一管理)
安全性中(依赖密钥存储)高(公钥体系)
适用场景超低端终端中高端终端

4.3 基于物理不可克隆函数的认证

这个就有点意思了。PUF,说白了就是利用芯片制造过程中的微小差异,生成一个独一无二的「芯片指纹」。这个指纹没法克隆,也没法预测。

为什么会这样?因为每颗芯片在制造时,晶体管的阈值电压、金属线的宽度都有微小的随机偏差。这些偏差会体现在电路的延迟、电流等物理特性上。PUF 就是把这些物理特性「读」出来,变成一串数字。

核心流程:

  1. 设备内置 PUF 电路。
  2. 服务器下发一个挑战(Challenge),通常是 64 位或 128 位的随机数。
  3. PUF 电路根据挑战,生成一个响应(Response)。
  4. 服务器用预存的「挑战-响应对」(CRP)数据库,验证响应是否正确。

关键点:PUF 的响应不是 100% 稳定的。温度、电压变化会导致响应出现比特翻转。所以,通常需要配合 模糊提取器(Fuzzy Extractor) 来纠错。

我在项目中遇到过一个问题:某款 PUF 芯片在 -20°C 和 +60°C 下,响应错误率高达 15%。如果不做纠错,认证几乎每次都失败。后来我们加了 BCH 纠错码,才把错误率降到 1% 以下。

优点:

  • 不需要存储密钥。密钥是「算」出来的,不是「存」出来的。
  • 抗物理攻击。你拆了芯片也没用,物理结构变了,PUF 响应就变了。
  • 轻量级。PUF 电路面积很小,功耗也低。

缺点:

  • CRP 数据库管理麻烦。每个设备有成千上万个 CRP,服务器要存很多。
  • 环境敏感。温度、电压、老化都会影响响应。
  • 目前成本还偏高,主要用在高端 IoT 设备上。

避坑指南:我曾经见过有人把 PUF 当成「万能密钥」。其实不是。PUF 更适合做「密钥生成器」,而不是直接做认证。通常的做法是:用 PUF 生成一个根密钥,然后用这个根密钥派生出 PSK 或私钥。这样既利用了 PUF 的物理不可克隆性,又兼容了现有的认证协议。

小结

三种方案,没有绝对的好坏。我的建议是:

  • 如果终端资源极度受限,成本敏感,用 PSK。但一定要做好密钥存储。
  • 如果终端有一定计算能力,需要大规模部署和远程管理,用 证书
  • 如果终端对安全性要求极高,且预算充足,用 PUF

嗯,其实在实际项目中,我经常把 PSK 和 PUF 结合起来用。用 PUF 生成 PSK,既解决了密钥存储问题,又保留了 PSK 的轻量级特性。这个思路,大家可以参考一下。