NTAG 424 NFC芯片的Python CRC计算



我目前正在使用NXP NTAG 424芯片,该芯片具有AES-128加密功能。

每当设置新密钥时,该芯片都需要计算crc32校验值(见数据表11.6.1/第67页(。根据数据表,crc是"根据IEEE Std802.3-2008计算的"。应用说明(6.16.1/第39页(甚至给出了一个例子:

new_key: F3847D627727ED3BC9C4CC050489B966
CRC32(new_key): 789DFADC

然而,当我尝试使用python和binascii crc32库复制结果时,结果不同:

>>> from binascii import unhexlify, crc32
>>> new_key = unhexlify('F3847D627727ED3BC9C4CC050489B966')
>>> print(hex(crc32(new_key)))
0x23056287     # Not the CRC I was looking for

该文档经常颠倒字节顺序,但是命令

>>> print(hex(crc32(new_key[::-1])))
0x9453faa7

也不会带来快乐。

所以问题是:我做错了什么?我试着查阅引用的标准,但以我的肤浅知识,我无法发现crc32标准和IEEE标准中引用的算法之间的任何区别。

示例的CRC是IEEE Std802.3(或等效的CCITT V.42(指定的32位CRC的COMPLEMENT,我在这里详细介绍了它。这是在该标签中使用标准CRC变体的另一种情况:与所有ISO/IEC 14443 a类标签一样,其错误检测(高达848kbit/s(使用IEEE Std802.3(或等效的CCITT V.42(指定的16位CRC变体,具有不同的初始值,并且缺少最终补码。

以下是与问题的测试向量相匹配的自包含代码:

# compute the CRC32 for NTAG424
# Ethernet / CCITT V42 CRC32, less final complement
def NTAG424CRC(m):
c = 0xFFFFFFFF
for b in m:
c ^= b;
for n in range(8):
c = (c>>1)^(0xEDB88320&-(c&1))
#   c ^= 0xFFFFFFFF  # required by Ethernet / CCITT V42
return c.to_bytes(4,'little')
# demo, expected value 789dfadc
print(NTAG424CRC(bytearray.fromhex('F3847D627727ED3BC9C4CC050489B966')).hex())

在线试用!

我做错了什么?

  • 相信制造商忠实地执行了自己的规范
  • 期望binascii.crc32的输出为big-endian;它是小字节序,在电信中必须如此才能保持CRC32的突发错误检测特性。在binascii.crc32的规范中,有一个int作为输出是一种疏忽,当使用bytearray作为输入时,几乎不可能出现字节序错误

我们可以也可能应该使用binascii.crc32,它是本机的,使用预先计算的表,因此速度要快得多(但可能更容易受到缓存相关的侧通道攻击(。

import binascii
# compute the CRC32 for NTAG424 using binascii.crc32
# Ethernet / CCITT V42 CRC32, less final complement
def NTAG424CRC(m):
return (binascii.crc32(m)&0xFFFFFFFF^0xFFFFFFFF).to_bytes(4,'little')
# &0xFFFFFFFF deals with negative output; it can be removed under Python 3
# ^0xFFFFFFFF undoes the complement rightly done by binascii.crc32
# demo, expected value 789dfadc
print(NTAG424CRC(bytearray.fromhex('F3847D627727ED3BC9C4CC050489B966')).hex())

在线试用!

最新更新