4. LoRaWAN入网流程:OTAA与ABP激活方式、Join-Request与Join-Accept流程、Session密钥生成

聊到LoRaWAN,绕不开的一个话题就是——终端设备怎么“加入”网络?

我刚开始做LoRa项目时,以为只要把设备上电、配置好频点就能通信。结果发现,设备发出去的数据,网关根本不认。后来才明白,入网这件事,远没我想的那么简单。

LoRaWAN定义了两种激活方式:OTAA(Over-The-Air Activation)和ABP(Activation By Personalization)。说白了,一个是在线申请入网,一个是提前写好身份信息直接干活。两种方式各有适用场景,我们一个一个说。

4.1 OTAA:空中激活,安全但流程复杂

OTAA是我个人最推荐的方式。设备每次上电,都要跟网络服务器“握手”,申请入网。这个过程会生成会话密钥,安全性更高。

OTAA的核心流程,其实就是两个报文:Join-RequestJoin-Accept

4.1.1 Join-Request:设备喊话“我要入网”

设备发送Join-Request时,包里带了三个关键信息:

  • AppEUI(JoinEUI):应用标识,告诉网络服务器“我想加入哪个应用”
  • DevEUI:设备唯一标识,相当于设备的身份证号
  • DevNonce:一个随机数,防止重放攻击

嗯,这里要注意:DevNonce是设备每次入网时随机生成的。网络服务器会记录所有用过的DevNonce,如果发现重复,直接拒绝入网。我在项目中就遇到过,某款模组因为随机数生成算法太弱,导致DevNonce重复,设备死活入不了网。后来换了硬件随机数生成器才解决。

4.1.2 Join-Accept:服务器说“你通过了”

网络服务器收到Join-Request后,会验证DevNonce是否重复。如果没问题,就回复Join-Accept。这个报文是加密的,密钥是AppKey(设备出厂时预置的根密钥)。

Join-Accept里包含:

  • AppNonce:服务器生成的随机数,用于派生会话密钥
  • NetID:网络标识
  • DevAddr:设备在网络中的短地址(32位)
  • RXDelayRX1DROffset:接收窗口参数

设备收到Join-Accept后,用AppKey解密,拿到这些参数。然后,最关键的一步来了——生成会话密钥。

4.2 会话密钥生成:从根密钥到会话密钥

OTAA入网成功后,设备和服务端会派生两个会话密钥:

  • NwkSKey(网络会话密钥):用于MAC层数据的加密和完整性校验
  • AppSKey(应用会话密钥):用于应用层数据的加密

这两个密钥是怎么来的?

LoRaWAN使用AES-128算法,以AppKey为根密钥,结合AppNonce、NetID、DevNonce等参数,通过特定的派生函数计算得出。说白了,就是拿一堆随机数和固定参数,做一次AES加密运算。

我记得有一次调试,设备入网后数据一直解密失败。查了半天,发现是设备端和服务端计算NwkSKey时,参数拼接顺序不一致。一个先拼AppNonce再拼NetID,另一个反过来。嗯,这种细节问题,真的让人头大。

密钥派生公式(简化版):

NwkSKey = aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16)
AppSKey = aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)

注意:0x01和0x02是区分网络密钥和应用密钥的固定字节。

4.3 ABP:个性化激活,简单但风险高

ABP就简单多了。设备出厂前,直接把DevAddr、NwkSKey、AppSKey烧录进设备。设备上电后,不需要任何握手流程,直接发数据。

听起来很方便对吧?但代价也很明显:

  • 安全性低:密钥是固定的,一旦泄露,整个网络都可能被攻击
  • 无法防重放:没有DevNonce机制,攻击者可以重放旧数据包
  • 网络切换困难:如果换网络服务器,所有设备都得重新烧录密钥

我曾经在一个项目中,客户坚持用ABP,理由是“省流量”。结果设备部署后,因为密钥被第三方工具抓包破解,导致整个网络被恶意注入假数据。后来全部换成OTAA,虽然每次入网多花了几百毫秒,但安全多了。

避坑指南:我曾经在ABP设备上吃过亏——设备长时间断电后重新上电,帧计数器(FCnt)归零,但服务器端记录的FCnt还是旧值。结果服务器认为数据包是重放攻击,直接丢弃。所以,如果非要用ABP,一定要处理好FCnt的持久化存储。

4.4 OTAA vs ABP:怎么选?

我个人的经验是:

场景 推荐方式 原因
消费类产品(如智能家居) OTAA 安全性高,支持密钥更新
工业传感器(固定部署) OTAA 即使部署环境固定,也建议用OTAA
极低功耗、无网络交互场景 ABP 省去入网流程,但要做好密钥管理
原型验证、实验室测试 ABP 快速验证,不用每次等入网

4.5 完整入网流程(OTAA)

为了让你更直观地理解,我画了一张流程图。你想想看,设备从发送Join-Request到开始传数据,中间经历了什么?

终端设备 网关 网络服务器 Join-Request 转发 验证DevNonce Join-Accept(加密) 解密Join-Accept 生成会话密钥 开始数据通信 加密数据

从这张图你能看到,OTAA入网其实就三步:

  1. 设备发Join-Request,网关转发给网络服务器
  2. 网络服务器验证后,回复加密的Join-Accept
  3. 设备解密,生成会话密钥,开始正常通信

个人小技巧:调试OTAA入网时,我习惯先用串口把Join-Request的原始数据打印出来,跟服务器收到的对比。很多时候入网失败,就是因为DevNonce或AppEUI的字节序搞反了。LoRaWAN用的是小端序,但有些SDK默认是大端序,这个坑我踩过不止一次。

4.6 小结

OTAA和ABP,说白了就是“安全但麻烦”和“简单但危险”的取舍。我个人建议,除非是实验室测试或极低功耗场景,否则一律用OTAA。毕竟物联网设备部署后,很难再OTA升级密钥,安全设计一定要做在前面。

会话密钥的生成,是整个入网流程的核心。理解AES-128的派生过程,能帮你快速定位入网失败的问题。嗯,这部分内容虽然偏理论,但实际调试时非常有用。


公众号:蓝海资料掘金营,微信deep3321