3、AES-128加密基础:分组密码模式(ECB/CBC/CTR)、LoRaWAN中使用的CMAC与CTR模式、加密算法选择原因

好,咱们进入第三讲。这一讲是LoRaWAN安全机制的「地基」——AES-128加密。说实话,很多做LoRa应用开发的工程师,对加密这块要么直接跳过,要么就是调库完事。但你要真想把LoRaWAN吃透,AES-128这块绕不过去。

我当年刚接触LoRaWAN时,也踩过坑。有一次客户反馈设备偶尔掉线,查了三天,最后发现是加密模式用错了。嗯,从那以后,我对AES的每个模式都格外上心。

3.1 什么是AES-128?

AES-128,全称是高级加密标准,密钥长度128位。说白了,就是一把128位的钥匙,去锁和解锁你的数据。

为什么LoRaWAN选128位而不是192或256?我个人的理解是:平衡。LoRaWAN设备大多是电池供电、算力有限的MCU。128位在安全强度和计算开销之间,找到了一个很好的平衡点。你想想看,一个STM32L0跑AES-128,一个块也就几十微秒。换成256,功耗和耗时都翻倍,但安全增益对IoT场景来说并不明显。

核心要点: AES-128不是一种「加密模式」,它是一种底层算法。真正决定怎么加密的,是分组密码模式——ECB、CBC、CTR这些。

3.2 分组密码模式:ECB、CBC、CTR

咱们先快速过一下这三种模式。我尽量用大白话讲,不堆公式。

3.2.1 ECB模式(电子密码本模式)

ECB是最简单的模式。每个16字节的明文块,独立用同一个密钥加密。

优点: 可以并行计算,速度快。

缺点: 相同的明文块,加密后得到相同的密文块。这在LoRaWAN里是致命的——攻击者能看出数据模式。

避坑指南: 我曾经见过有人用ECB模式加密传感器数据。结果呢?温度值从25.0变成25.1,密文只有最后几个字节变了。攻击者一看就知道温度在缓慢上升。LoRaWAN协议里明确禁止使用ECB模式。

3.2.2 CBC模式(密码分组链接模式)

CBC模式引入了「链接」机制。每个明文块先与前一个密文块异或,再加密。第一个块需要一个初始向量(IV)。

优点: 相同的明文块,加密后密文不同。安全性比ECB高很多。

缺点: 不能并行加密,而且如果中间一个密文块损坏,后面所有块都解不出来。

LoRaWAN里,CBC模式主要用于密钥派生,而不是直接加密数据。为什么?因为LoRaWAN的密钥派生过程是离线的、一次性的,不需要实时性,CBC的串行特性完全够用。

3.2.3 CTR模式(计数器模式)

CTR模式是我个人最喜欢的模式。它把加密变成了「流加密」——用一个不断递增的计数器,生成密钥流,然后与明文异或。

优点:

  • 可以并行加密/解密
  • 不需要填充(LoRaWAN数据包长度不固定,这点太重要了)
  • 加解密使用相同的操作(异或),硬件实现简单

缺点: 计数器绝对不能重复使用。一旦重复,密钥流相同,异或就能破解。

我的经验: 在LoRaWAN中,CTR模式用于数据帧加密。每个数据帧都有一个唯一的帧计数器(FCnt),这就保证了计数器不会重复。设计协议的人考虑得很周全。

3.3 LoRaWAN中使用的CMAC与CTR模式

好,重点来了。LoRaWAN用了两种AES-128模式:CMACCTR

3.3.1 CMAC(基于AES的消息认证码)

CMAC不是加密模式,它是消息认证码。它的作用是:确保数据没有被篡改,并且验证发送方的身份。

LoRaWAN里,CMAC用于生成MIC(消息完整性码)。每个上行/下行数据帧末尾都有4字节的MIC。

具体怎么算的?我简化一下流程:

// 伪代码:LoRaWAN MIC计算(简化版)
// 输入:数据帧内容(不含MIC本身)、NwkSKey、方向位、帧计数器
// 输出:4字节MIC

B0 = 0x49 || 方向位(1字节) || 设备地址(4字节) || 帧计数器(4字节) || 0x00 || 数据长度(1字节)
CMAC_input = B0 || 数据帧内容
MIC = AES_CMAC(NwkSKey, CMAC_input)  // 取前4字节

你可能会问:为什么是4字节?不是8字节或16字节?嗯,这是LoRaWAN的权衡。4字节的碰撞概率在IoT场景下可以接受,而且节省了宝贵的空中传输时间。我记得有一次做项目,客户非要改成8字节MIC,结果一算,每包数据多4字节,电池寿命直接降了15%。后来还是改回来了。

3.3.2 CTR模式在LoRaWAN中的应用

CTR模式用于加密数据帧的FRMPayload(应用层数据)。

LoRaWAN的CTR模式有个特殊设计:它使用AES-128加密一个计数器块,然后与明文异或。计数器块的格式如下:

// 计数器块格式(16字节)
// 0x01 | 方向位(1字节) | 设备地址(4字节) | 帧计数器(4字节) | 块计数器(4字节) | 0x00(1字节)

A1 = 0x01 || Dir(1) || DevAddr(4) || FCnt(4) || BlockCnt(4) || 0x00(1)
KeyStream = AES_ENC(AppSKey, A1)
Ciphertext = Plaintext XOR KeyStream

这里有个细节:块计数器从0开始,每加密16字节加1。如果数据只有5字节,那就只取密钥流的前5字节。这就是CTR模式不需要填充的原因——太适合LoRaWAN这种变长数据包了。

关键区别:
  • CMAC 使用 NwkSKey(网络会话密钥)——保证网络层完整性
  • CTR 使用 AppSKey(应用会话密钥)——保证应用层机密性
两者密钥不同,职责分离。这是LoRaWAN安全设计的精髓之一。

3.4 加密算法选择原因

最后,咱们聊聊为什么LoRaWAN偏偏选了AES-128,而不是别的算法。

原因一:硬件支持广泛

几乎所有LoRaWAN芯片(如SX126x、STM32WL系列)都内置了AES-128硬件加速器。软件实现也很轻量。相比之下,像ChaCha20这种流密码,虽然也很优秀,但硬件支持远不如AES普及。

原因二:NIST标准,经过充分验证

AES是NIST标准,被全球密码学家研究了20多年,没有发现实质性漏洞。LoRaWAN作为IoT标准,选一个经过时间考验的算法,是稳妥的选择。

原因三:CTR+CMAC的组合拳

CTR提供机密性,CMAC提供完整性。两者都基于AES-128,可以用同一套硬件加速器。你想想看,如果机密性用AES,完整性用SHA,那MCU就得跑两套算法,功耗和代码体积都上去了。

我的建议: 如果你在开发LoRaWAN设备,千万别自己实现AES。用芯片厂商提供的硬件库,或者mbedTLS这样的成熟软件库。我曾经见过有人手写AES,结果密钥扩展写错了,设备能加密但解不出来——那叫一个惨。

好,这一讲就到这里。下一讲我们会深入LoRaWAN的密钥派生过程,看看AppKey、NwkSKey、AppSKey到底是怎么从根密钥变出来的。到时候你会更理解为什么AES-128的CBC模式在密钥派生中这么重要。