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终端设备在出厂时,都会烧录两个根密钥:AppKey和NwkKey。注意,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 数据加密流程:谁加密什么?
搞清楚了密钥的用途,我们来看看实际通信中它们是怎么配合的。我画了一张流程图,帮你理清整个加密链路:
从这张图你能看到:
- 上行数据:设备用NwkSKey加密MAC层(比如确认帧、重传控制),用AppSKey加密你的业务数据(比如温度、湿度)。网络服务器收到后,用NwkSKey解密MAC层,然后把加密的应用负载转发给应用服务器。
- 下行数据:反过来,网络服务器用NwkSKey加密MAC命令,应用服务器用AppSKey加密应用数据,最后拼成一个完整的帧发给设备。
关键点:网络服务器只能看到MAC层信息(比如信号强度、帧计数),但看不到你的业务数据。应用服务器只能解密业务数据,但看不到网络层的控制信息。这就是分层加密的好处。
2.5 实际项目中的密钥管理建议
说了这么多理论,最后分享几个我在项目中踩过的坑和总结的经验:
- 根密钥的存储:千万别把AppKey和NwkKey明文写在代码里。我建议用硬件安全模块(HSM)或者安全元件(SE)来存储。如果成本敏感,至少也要用加密存储+动态解密的方式。
- 会话密钥的更新:LoRaWAN规范允许设备在特定条件下重新入网来刷新会话密钥。我个人习惯是设置一个定时器,比如每24小时强制重新入网一次。这样即使某个会话密钥泄露,影响范围也有限。
- 密钥的备份:我曾经遇到过一个客户,设备批量生产时把AppKey写错了,结果所有设备都无法入网。后来我们建立了严格的密钥生成和校验流程:生成后先在一台测试设备上验证,确认能正常入网通信,再批量烧录。
- 1.0.x与1.1的兼容:如果你还在用1.0.x版本,记住它只有一个根密钥AppKey。NwkSKey和AppSKey都由AppKey派生。1.1版本引入NwkKey后,安全性更高,但需要网络服务器和应用服务器都支持。升级前一定要确认兼容性。
重要提醒:千万不要在生产环境中使用固定的DevNonce或JoinNonce。我见过有厂商为了调试方便,把DevNonce写死成0x0001,结果所有设备入网后会话密钥都一样。这在安全上等于裸奔。
好了,关于LoRaWAN的密钥体系,今天就聊到这里。这四把钥匙的关系搞清楚了,后面讲加密通信实现就顺理成章了。记住一句话:根密钥保终身,会话密钥保一时,分层加密保安全。