我目前正在进行一个非常简单的ZigBee绿色电源(GP)终端设备实现。目前,我的问题是如何生成正确的MIC (消息标识码)。
我已经有一个AES-CCM实现,并测试它与测试向量的ZigBee绿色电源来自ZigBee专业规范。问题是我得到的结果是不正确的(这与规范中的结果不一样)。
我还试图从规范中用其他测试向量(非GP向量)来验证我的实现,结果是正确的。所以,我的算法似乎是正确的。
在计算GP MIC码与正常的ZigBee MIC有什么不同吗?也许有人有另一个正在为ZigBee GP工作的实现??
附加信息:
我使用的ZigBee规范可以在这里获得:https://zigbeealliance.org/wp-content/uploads/2019/11/docs-05-3474-21-0csg-zigbee-specification.pdf#
正在工作的测试向量载于上述文件附件C.3。
绿色电源版本的测试矢量载于附件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: 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是使用nonce创建的(参见上文)。通常,AddAuthData和消息块是连接的。但对于绿色电源版本,据我所知,没有消息块可用。因此,B1 .Bn仅使用AddAuthData创建。,我在这儿吗??
B1 = AddAuthData
B1 = 0x00 0x0B 0x8C 0x10 0x21 0x43 0x65 0x87 0x02 0x00 0x00 0x00 0x20 0x00 0x00 0x00每个Bi块都使用AES-CBC算法E.Bi与前面生成的Xi结果为xor。初始向量X0是一个长度为16字节的全零位块。X_i+1 = E(Key,Xi XOR Bi) for i=0.N
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发布于 2021-03-10 07:01:41
下面是一个详细的使用Python源代码的AES-128-CCM*加密:*
发布于 2019-01-04 09:45:08
AES-CCM*是AES-CBC (认证)和AES-CTR (加密)的组合.
身份验证转换在16B Bi缓冲区上运行AES-CBC。B0是由Nonce构建的,B1,B2,..,Bn是解析AuthData的结果,其定义是:
AuthData = AddAuthData || PlaintextData由于您没有有效负载,所以PlaintextData是空的,在您的情况下是AuthData = AddAuthData。
注意,您的B0定义不正确。除了m的长度(即有效负载长度)外,在Nonce之后没有填充。由于您没有有效负载(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使用正确的128 B键,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 || CounterFlags与用于B0计算的基本相同,但只保留了最不重要的3位。然后Flags = 0x01和Ai是:
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。
https://stackoverflow.com/questions/46486884
复制相似问题