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

聊LoRaWAN安全,绕不开的就是这四把钥匙:AppKey、NwkKey、AppSKey、NwkSKey。很多刚入行的朋友容易搞混,觉得名字长得差不多,功能也分不清。我刚开始接触的时候也犯过这个错,后来在一次实际部署中吃了亏,才彻底搞明白它们各自的分工。

说白了,这四把钥匙就是LoRaWAN网络的安全基石。它们负责两件事:网络接入认证数据加密传输。一个管你能不能连进来,一个管你传的东西别人看不懂。

2.1 密钥从哪里来?——根密钥的生成

我们先从根上说起。LoRaWAN 1.0.x和1.1版本在密钥体系上有些差异,我这里以目前主流的1.0.x版本为例讲解,1.1版本我会在最后做个对比说明。

每个LoRaWAN终端设备在出厂时,都会烧录两个根密钥:AppKeyNwkKey。注意,1.0.x版本其实只有一个根密钥AppKey,NwkKey是1.1版本才引入的。但为了让你理解完整的密钥体系,我统一按1.1的视角来讲,这样你回头看1.0.x也能融会贯通。

核心原则:根密钥永远不出设备,也不出网络服务器。所有会话密钥都由根密钥派生而来。

这两个根密钥是怎么生成的呢?我个人习惯的做法是:

  • AppKey:由应用开发者生成,长度为16字节(AES-128)。它属于应用层,用于派生出AppSKey(应用会话密钥)。
  • NwkKey:由网络运营商或设备制造商生成,同样16字节。它属于网络层,用于派生出NwkSKey(网络会话密钥)。

你可能会问:为什么要分成两个?嗯,这里有个设计上的考量——职责分离。网络层只管网络接入和MAC命令,应用层只管你的业务数据。两者用不同的密钥加密,就算网络层被攻破,应用数据依然是安全的。反过来也一样。

我的经验:在实际项目中,我建议把AppKey和NwkKey分开存储在不同的安全元件中。如果条件不允许,至少也要用不同的密钥管理策略。我曾经见过一个项目,把两个密钥写死在同一个配置文件中,结果一泄露全完蛋。

2.2 会话密钥的派生过程

根密钥是静态的,但实际通信中用的是会话密钥。会话密钥在每次OTAA(Over-The-Air Activation)入网时动态生成。为什么要动态生成?你想想看,如果一直用同一个密钥,时间长了被破解的风险就越大。动态派生相当于每次通信都换一把新锁。

派生过程用到了AES-CMAC算法。LoRaWAN规范里定义了一个伪随机函数:

// 伪代码:派生AppSKey
AppSKey = aes128_encrypt(AppKey, 0x02 | DevNonce | JoinNonce | ...)

// 派生NwkSKey
NwkSKey = aes128_encrypt(AppKey, 0x01 | DevNonce | JoinNonce | ...)

这里的关键输入参数是:

  • DevNonce:设备端生成的随机数,每次入网都不同
  • JoinNonce:网络服务器生成的随机数
  • 固定字节:0x01和0x02用于区分派生的是哪个密钥

你看,只要DevNonce或JoinNonce有一个变化,派生出来的会话密钥就完全不同。这就是为什么每次重新入网,通信密钥都会刷新。

避坑指南:我曾经遇到过一个设备,它的DevNonce生成逻辑有bug,每次上电都生成相同的随机数。结果就是,每次入网拿到的会话密钥都一样。这在安全上等于没换密钥。所以,一定要确保随机数生成器的质量,别用简单的伪随机算法。

2.3 四把钥匙的用途对比

好了,现在我们来逐一看看这四把钥匙到底干什么用。我整理了一个表格,方便你对照:

密钥名称 长度 所属层级 主要用途 生命周期
AppKey 16字节 应用层 派生AppSKey;用于Join-Request/Accept消息的完整性校验 永久(设备生命周期)
NwkKey 16字节 网络层 派生NwkSKey;用于MAC命令的加密和完整性校验 永久(设备生命周期)
AppSKey 16字节 应用层 加密应用层负载(FRMPayload) 会话期(入网到重新入网)
NwkSKey 16字节 网络层 加密MAC命令;计算消息完整性校验码(MIC) 会话期(入网到重新入网)

从这个表格你能看出:

  • AppKey和NwkKey是根密钥,一辈子不变。它们就像你的身份证号,生下来就定了。
  • AppSKey和NwkSKey是会话密钥,每次入网都变。它们就像你住酒店的房间卡,退房就失效。

2.4 数据加密流程:谁加密什么?

搞清楚了密钥的用途,我们来看看实际通信中它们是怎么配合的。我画了一张流程图,帮你理清整个加密链路:

LoRaWAN 加密通信流程 终端设备 网络服务器 应用服务器 上行数据(NwkSKey加密MAC + AppSKey加密负载) 下行数据(NwkSKey加密MAC + AppSKey加密负载) 转发应用负载(AppSKey加密) 图例 设备端 网络服务器 应用服务器

从这张图你能看到:

  • 上行数据:设备用NwkSKey加密MAC层(比如确认帧、重传控制),用AppSKey加密你的业务数据(比如温度、湿度)。网络服务器收到后,用NwkSKey解密MAC层,然后把加密的应用负载转发给应用服务器。
  • 下行数据:反过来,网络服务器用NwkSKey加密MAC命令,应用服务器用AppSKey加密应用数据,最后拼成一个完整的帧发给设备。

关键点:网络服务器只能看到MAC层信息(比如信号强度、帧计数),但看不到你的业务数据。应用服务器只能解密业务数据,但看不到网络层的控制信息。这就是分层加密的好处。

2.5 实际项目中的密钥管理建议

说了这么多理论,最后分享几个我在项目中踩过的坑和总结的经验:

  1. 根密钥的存储:千万别把AppKey和NwkKey明文写在代码里。我建议用硬件安全模块(HSM)或者安全元件(SE)来存储。如果成本敏感,至少也要用加密存储+动态解密的方式。
  2. 会话密钥的更新:LoRaWAN规范允许设备在特定条件下重新入网来刷新会话密钥。我个人习惯是设置一个定时器,比如每24小时强制重新入网一次。这样即使某个会话密钥泄露,影响范围也有限。
  3. 密钥的备份:我曾经遇到过一个客户,设备批量生产时把AppKey写错了,结果所有设备都无法入网。后来我们建立了严格的密钥生成和校验流程:生成后先在一台测试设备上验证,确认能正常入网通信,再批量烧录。
  4. 1.0.x与1.1的兼容:如果你还在用1.0.x版本,记住它只有一个根密钥AppKey。NwkSKey和AppSKey都由AppKey派生。1.1版本引入NwkKey后,安全性更高,但需要网络服务器和应用服务器都支持。升级前一定要确认兼容性。

重要提醒:千万不要在生产环境中使用固定的DevNonce或JoinNonce。我见过有厂商为了调试方便,把DevNonce写死成0x0001,结果所有设备入网后会话密钥都一样。这在安全上等于裸奔。

好了,关于LoRaWAN的密钥体系,今天就聊到这里。这四把钥匙的关系搞清楚了,后面讲加密通信实现就顺理成章了。记住一句话:根密钥保终身,会话密钥保一时,分层加密保安全


专注资料整理