LoRaWAN 密钥体系:AppKey、NwkKey、AppSKey、NwkSKey 的生成与作用

聊 LoRaWAN 安全,绕不开的就是密钥。很多刚入行的朋友,看到 AppKey、NwkKey、AppSKey、NwkSKey 这四个名字就头大。说实话,我当年也迷糊过一阵子。

但你要想明白一件事:LoRaWAN 的密钥设计,本质上就是一套「谁该知道什么」的权限划分。搞懂了这一点,后面看安全更新机制就顺了。

1.1 从一把钥匙到两把钥匙:LoRaWAN 1.0.x 与 1.1 的区别

先说说历史。LoRaWAN 1.0.x 时代,只有一套密钥体系:

  • AppKey:根密钥,用来派生其他密钥
  • AppSKey:应用会话密钥,加密应用数据
  • NwkSKey:网络会话密钥,加密网络层数据

看起来挺简洁对吧?但问题来了——AppSKey 和 NwkSKey 都是从同一个 AppKey 派生出来的。这意味着,网络服务器和应用服务器共享了同一个根密钥。你想想看,这合理吗?

我曾经踩过的坑:在 1.0.x 版本中,如果网络服务器被攻破,攻击者拿到 AppKey 就能推导出 AppSKey,进而解密所有应用数据。这在很多行业场景下是致命的。

所以 LoRaWAN 1.1 做了关键改进:把一把钥匙拆成了两把。

  • NwkKey:网络根密钥,只归网络服务器管
  • AppKey:应用根密钥,只归应用服务器管

这样一来,网络侧和应用侧彻底解耦。我个人觉得,这是 1.1 版本最值得升级的理由之一。

1.2 密钥的生成:从哪里来?

所有密钥的源头,其实都在设备出厂那一刻就定好了。LoRaWAN 终端设备在烧录时,会写入两个关键值:

  • DevEUI:全球唯一设备标识,类似设备的身份证
  • AppKey(或 NwkKey + AppKey,取决于版本)

这些根密钥是怎么生成的?标准做法是:

// 伪代码示意:根密钥生成
AppKey = AES_128_ECB_encrypt(RootKey, DevEUI || JoinNonce)
// 实际生产环境中,RootKey 由密钥管理系统(KMS)安全生成

嗯,这里要注意:根密钥必须由安全的随机数生成器产生。我在项目中见过有人直接用固定字符串当 AppKey,结果可想而知——整个网络的安全形同虚设。

1.3 会话密钥的派生:OTAA 流程中的关键步骤

设备入网(Join)时,会通过 OTAA 流程派生出会话密钥。这个过程我建议你仔细看,因为它是整个安全体系的基石。

当设备发送 Join Request 后,网络服务器会回复 Join Accept。这个 Join Accept 里面包含一个关键参数——AppNonce(或 JoinNonce)。

然后,双方用这个 Nonce 加上其他参数,通过 AES 算法派生出会话密钥:

// LoRaWAN 1.0.x 的派生方式
NwkSKey = aes128_encrypt(AppKey, 0x01 || AppNonce || NetID || DevNonce || pad16)
AppSKey = aes128_encrypt(AppKey, 0x02 || AppNonce || NetID || DevNonce || pad16)

// LoRaWAN 1.1 的派生方式
FNwkSIntKey = aes128_encrypt(NwkKey, 0x01 || JoinNonce || JoinEUI || DevNonce || pad16)
SNwkSIntKey = aes128_encrypt(NwkKey, 0x03 || JoinNonce || JoinEUI || DevNonce || pad16)
NwkSEncKey  = aes128_encrypt(NwkKey, 0x04 || JoinNonce || JoinEUI || DevNonce || pad16)
AppSKey     = aes128_encrypt(AppKey, 0x05 || JoinNonce || JoinEUI || DevNonce || pad16)

关键点:注意看 1.1 版本中,NwkKey 派生了三个网络密钥,而 AppKey 只派生了 AppSKey。这就是「职责分离」的具体实现。

1.4 各密钥的作用:谁用谁?

我把四个核心密钥的作用整理成了一张表,方便你对照:

密钥名称 所属版本 存储位置 主要用途
AppKey 1.0.x / 1.1 终端 + 应用服务器 派生 AppSKey;1.0.x 中还派生 NwkSKey
NwkKey 1.1 新增 终端 + 网络服务器 派生所有网络层会话密钥
AppSKey 1.0.x / 1.1 终端 + 应用服务器 加密/解密应用层负载(FRMPayload)
NwkSKey 1.0.x 终端 + 网络服务器 计算 MIC、加密网络头(FHDR)

我的建议:如果你还在用 1.0.x,尽快评估升级到 1.1。虽然迁移有成本,但安全收益是实打实的。尤其是做智慧抄表、工业传感器这类对数据保密性要求高的场景,1.1 的密钥分离设计能省掉很多合规上的麻烦。

1.5 密钥的生命周期管理

密钥不是永久的。每次设备重新入网(Rejoin),会话密钥都会重新派生。但根密钥(AppKey / NwkKey)是写死在设备里的,除非物理更换设备,否则不会变。

这就引出一个问题:如果根密钥泄露了怎么办?

说实话,这是 LoRaWAN 目前的一个短板。根密钥泄露后,攻击者可以伪造设备身份、解密历史数据。唯一的补救措施就是——换设备。

所以我在项目里一直强调:根密钥的存储和分发,必须用硬件安全模块(HSM)或安全元件(SE)。别图省事把密钥明文写在配置文件里,那是给自己挖坑。

1.6 密钥体系全景图

下面这张图,是我根据 1.1 版本的密钥体系画的。你可以看到,从根密钥到会话密钥,再到具体的加密用途,整个链路非常清晰:

LoRaWAN 1.1 密钥体系全景图 NwkKey(网络根密钥) AppKey(应用根密钥) AES-128 派生 FNwkSIntKey SNwkSIntKey NwkSEncKey AppSKey 上行 MIC 计算 (FCnt 递增验证) 下行 MIC 计算 (FCnt 递减验证) 网络层加密 (FHDR / FOpts) 应用层加密 (FRMPayload) 关键设计原则 1. NwkKey 只派生网络密钥,AppKey 只派生应用密钥 2. 网络服务器无法获取 AppSKey,应用服务器无法获取网络密钥 3. 每次入网都会重新派生会话密钥,保证前向安全性 4. 根密钥必须存储在安全硬件中,不可导出

1.7 避坑指南:我见过的密钥管理翻车现场

做了这么多年物联网安全,我见过太多密钥管理上的问题了。挑几个典型的说说:

  • 密钥硬编码在固件里——有人把 AppKey 直接写在代码里,结果固件被反编译后全网密钥都暴露了。我建议用安全芯片存储根密钥。
  • 所有设备用同一个 AppKey——这相当于一把钥匙开所有锁。一旦泄露,整个网络都得重建。
  • 忽略 JoinNonce 的随机性——JoinNonce 如果不够随机,会话密钥就可能被预测。我在一个项目中排查过这个问题,最后发现是随机数生成器初始化种子没做好。
  • 1.0.x 升级到 1.1 时密钥没迁移——有些厂商直接在 1.0.x 的设备上刷 1.1 的固件,但根密钥还是旧的 AppKey,导致 NwkKey 缺失。嗯,这会导致入网失败。

总结一下:LoRaWAN 的密钥体系,说白了就是一套「最小权限原则」的落地。1.0.x 版本把网络和应用绑在一起,1.1 版本把它们拆开了。理解了这个演进逻辑,你就能明白为什么安全更新机制要这么设计——因为密钥的更新,本质上就是权限的重新分配。