3、密钥体系:AppKey、NwkKey、AppSKey、NwkSKey的诞生与职责

聊完了LoRaWAN的空中握手,咱们得深入聊聊它的“心脏”——密钥体系。

很多人刚开始接触LoRaWAN安全时,会被一堆Key搞晕:AppKey、NwkKey、AppSKey、NwkSKey…… 这玩意儿到底谁管谁?

我当年第一次看规范时,也花了整整一个下午才理清。说白了,LoRaWAN的密钥体系就是一套“双通道”的权限管理:网络通道和应用通道。两者互不干扰,各司其职。

3.1 密钥的“根”:根密钥(Root Key)

在LoRaWAN 1.0.x版本里,只有一个根密钥叫 AppKey。到了1.1版本,为了更精细的安全控制,分成了两个根密钥:NwkKey 和 AppKey。

嗯,这里要注意:1.1版本里的AppKey和1.0.x的AppKey,名字一样,但职责已经变了。咱们以最新的1.1版本为准来讲。

核心概念:根密钥是设备在出厂时烧录的“种子”。它不参与日常通信加密,只用来“生”其他会话密钥。

这两个根密钥的诞生方式很简单:

  • OTAA入网方式:由应用服务器或网络服务器生成,在设备注册时预置到终端中。
  • ABP入网方式:直接预置在设备和服务器中,但这种方式安全性较低,我个人不太推荐在生产环境中大规模使用。

我曾经在一个智慧农业项目中,客户坚持用ABP方式,结果设备被恶意克隆,数据全乱了。后来全部改成OTAA,问题才解决。

3.2 会话密钥的诞生:从根密钥到会话密钥

设备入网时,会经历一次“Join流程”。在这个过程中,根密钥通过一个固定的派生算法(AES-CMAC),生成两组会话密钥:

密钥名称 长度 用途 由谁持有
NwkSKey 128 bit 网络层加密与完整性校验 终端 + 网络服务器
AppSKey 128 bit 应用层数据加密 终端 + 应用服务器

你想想看,为什么要把网络密钥和应用密钥分开?

说白了,就是职责分离。网络服务器只管转发和确认数据包,它不需要知道你的传感器数据是什么。应用服务器只管解密数据,它不需要参与网络层的完整性校验。

我的经验:在LoRaWAN 1.0.x中,NwkSKey和AppSKey都是从同一个AppKey派生出来的。但1.1版本中,NwkSKey从NwkKey派生,AppSKey从AppKey派生。这样即使应用服务器被攻破,网络层仍然是安全的。

3.3 密钥派生流程详解

咱们来看看具体的派生过程。以OTAA为例,设备发送Join Request后,服务器返回Join Accept。在这个过程中,密钥是这样生成的:

  1. 计算NwkSKey:NwkSKey = aes128_cmac(NwkKey, 0x01 | JoinNonce | NetID | DevNonce | pad16)
  2. 计算AppSKey:AppSKey = aes128_cmac(AppKey, 0x02 | JoinNonce | NetID | DevNonce | pad16)
  3. 计算FNwkSIntKey(1.1版本新增):用于前向网络完整性校验。
  4. 计算SNwkSIntKey(1.1版本新增):用于后向网络完整性校验。

嗯,这里要注意:1.1版本把网络完整性校验也拆成了两个方向,防止中间人篡改。

避坑指南:我曾经遇到过一个问题:设备入网后,数据偶尔解密失败。排查了半天,发现是服务器端和终端使用的JoinNonce不一致。记住,JoinNonce必须严格递增,且服务器和终端要同步好。

3.4 密钥的生命周期

会话密钥不是永久的。每次设备重新入网(Rejoin),都会生成新的NwkSKey和AppSKey。旧的密钥立即失效。

这样做的好处很明显:

  • 前向安全性:即使某次会话的密钥泄露,攻击者也无法解密历史数据。
  • 后向安全性:攻击者无法预测未来的会话密钥。

我个人习惯在设备每次掉线重连后,强制触发一次Rejoin,确保密钥更新。虽然会增加一点网络开销,但安全性的提升是值得的。

3.5 密钥体系全景图

下面这张图,是我自己整理的一个密钥体系结构图。你可以看到,从根密钥到会话密钥,再到具体的加密和校验,层次非常清晰。

LoRaWAN 1.1 密钥体系结构图 LoRaWAN 1.1 密钥体系结构 NwkKey(网络根密钥) AppKey(应用根密钥) FNwkSIntKey(前向网络完整性密钥) SNwkSIntKey(后向网络完整性密钥) NwkSEncKey(网络层加密密钥) AppSKey(应用层加密密钥) 说明: 1. 所有会话密钥在每次入网时重新生成,旧密钥立即失效。 2. 网络服务器只持有网络相关密钥,应用服务器只持有AppSKey。

3.6 密钥存储与安全建议

密钥存储是个容易被忽视的问题。很多开发者把密钥硬编码在代码里,这是非常危险的。

我建议:

  • 终端设备:使用硬件安全模块(HSM)或安全元件(SE)存储根密钥。如果成本受限,至少要用MCU的加密存储区。
  • 网络服务器:使用密钥管理服务(KMS)或硬件加密机。不要明文存储在数据库里。
  • 应用服务器:同样使用KMS,且与网络服务器的密钥管理分开。

我曾经踩过的坑:在一个项目中,我们把AppKey直接写在了固件的配置文件中。结果固件被逆向,所有设备的AppKey都暴露了。后来我们改用每台设备独立烧录密钥,并启用了固件加密,才彻底解决这个问题。

3.7 小结

LoRaWAN的密钥体系,说白了就是一套“双根多派生”的架构。NwkKey管网络,AppKey管应用,两者互不干扰。会话密钥每次入网都重新生成,保证了前向和后向安全性。

你只要记住:根密钥是种子,会话密钥是果实。种子要藏好,果实要勤换。