ZigBee Green Power AES-CCM

时间:2017-09-29 10:27:25

标签: encryption aes zigbee

我目前正在开发一种非常简单的ZigBee Green Power(GP)终端设备实现。目前,我的问题是如何生成正确的MIC(消息识别码) 我已经有了AES-CCM实现,并使用ZigBee Pro规范的ZigBee Green Power测试向量进行了测试。问题是我得到的结果不正确(它与规范中的不一样)。
我还尝试使用规范中的其他测试向量(非GP测试向量)验证我的实现,结果是正确的。所以,我的算法似乎是正确的。

计算GP MIC代码与普通ZigBee MIC有区别吗?也许有人有另一个适用于ZigBee GP的实现?

其他信息:

我使用的ZigBee规范可在此处获取:http://www.zigbee.org/zigbee-for-developers/network-specifications/zigbeepro/#

正在运行的测试向量在上述文件的附录C.3中。

Green Power版本的测试向量见附件H.2。为了完整起见,参数如下(附件H.2.3):

Key: 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCa, 0xCb, 0xCc, 0xCd, 0xCe, 0xCf
NWK Frame Control: 0x8C
GPD Src ID: 0x87654321
Security Frame Counter: 0x00000002
GPD Command ID: 0x02
No data Payload

规范说nonce的构造如下:

Nonce: SRC ID || SRC ID || Frame Counter || 0x05
Nonce: 0x21 0x43 0x65 0x87 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00 0x05

对于计算,需要'a'值:

a = Header || Payload
Header = NWK FC || NWK Ext FC || SRC ID || Frame Counter
Header = 0x8C 0x10 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00
Payload = GPD Command ID = 0x20
a = 0x8C 0x10 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00 0x20

最后,为了计算AES-CBC算法,需要以下参数:

length(a) = 0x0B
L(a) = 0x00 0x0B (big endian encoding of length(a))
AddAuthData = L(a) || a || padding
AddAuthData = 0x00 0x0B 0x8C 0x10 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00 0x20 0x00 0x00 0x00
Flags = 0x49
B0 = Flags || Nonce || padding
B0 = 0x49 0x21 0x43 0x65 0x87 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00 0x05 0x00 0x00

为了生成MIC代码,该算法与加密密钥和B0 ... Bi块(每个16字节)一起使用。 B0是使用随机数创建的(见上文)。通常AddAuthData和消息块连接在一起。但对于绿色电源版本,据我所知,没有可用的消息块。因此,B1 ... Bn仅使用AddAuthData创建。 我在这儿吗?

B1 = AddAuthData
B1 = 0x00 0x0B 0x8C 0x10 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00 0x20 0x00 0x00 0x00

AES-CBC算法E与每个Bi块一起使用。 Bi与之前生成的Xi结果进行xor'd。初始向量X0是全零位块,长度为16字节。     对于i = 0 ... N

,X_i + 1 = E(Key,Xi XOR Bi)

AES计算的结果是16字节值。但只使用了最左边的4个字节。预期的结果是:

U = 0xCF 0x78 0x7E 0x72

但我明白了:

X2 = 02 1C 9F 9C 40 3A 27 B4 9A 31 64 EA 17 CF 69 D3
U = 0x02 0x1C 0x9F 0x9C

2 个答案:

答案 0 :(得分:2)

这是使用 Python 源代码的详细 AES-128-CCM* 加密:ZigBee frame encryption with AES-128-CCM*

答案 1 :(得分:0)

AES-CCM *是AES-CBC(身份验证)和AES-CTR(加密)的组合。

身份验证转换在16B Bi缓冲区上运行AES-CBC。 B0是根据Nonce构建的,而B1,B2,..,Bn是解析AuthData的结果,其定义为:

AuthData = AddAuthData || PlaintextData

由于没有有效负载,PlaintextData为空,因此AuthData = AddAuthData为空。

请注意,您的B0定义不正确。 Nonce之后没有填充,但是m的长度(即有效载荷长度)没有填充。由于您没有有效载荷(l(m)=0),因此结果与此处的填充相同。但是B0的正确定义是:

B0 = Flags || Nonce || l(m)

这是Bi缓冲区(不带0x前缀的十六进制格式):

B0 = 49 21 43 65 87 21 43 65 87 02 00 00 00 05 00 00
B1 = 00 0B 8C 10 21 43 65 87 02 00 00 00 20 00 00 00

使用正确的128b密钥,AES-CBC步骤将产生以下结果:

X0 = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
B0 = 49 21 43 65 87 21 43 65 87 02 00 00 00 05 00 00

X1 = 14 5B B8 1F DE D7 99 45 9D 9B 77 51 B7 31 A3 C1
B1 = 00 0B 8C 10 21 43 65 87 02 00 00 00 20 00 00 00

X2 = 02 1C 9F 9C 40 3A 27 B4 9A 31 64 EA 17 CF 69 D3

总结一下,您到目前为止是正确的,但是您还没有完成!您得到的不是U,而是T身份验证标签(未加密):T = 02 1C 9F 9C。要获得U,您应该运行加密转换(即使您没有要加密的有效负载)。

加密转换使用AES-CTR。计数器称为Ai,其定义为:

Ai = Flags || Nonce || Counter

FlagsB0计算中使用的基本相同,只是保留了3个最低有效位。然后Flags = 0x01Ai是:

A0 = 01 21 43 65 87 21 43 65 87 02 00 00 00 05 00 00
A1 = 01 21 43 65 87 21 43 65 87 02 00 00 00 05 00 01
A2 = 01 21 43 65 87 21 43 65 87 02 00 00 00 05 00 02
...

A1,A2,..,An用于加密您不感兴趣的有效负载。但是A0用于生成U加密标签。该操作基本上是U = E(Key, A0) xor T

       A0 = 01 21 43 65 87 21 43 65 87 02 00 00 00 05 00 00
E(Key,A0) = CD 64 E1 EE 37 25 CF 25 AD 84 00 F0 5C B4 9B 03
        T = 02 1C 9F 9C
        U = CF 78 7E 72

在这里,您得到了预期的结果U = 0xCF 0x78 0x7E 0x72