NTAG 424 NFC 芯片的 Python CRC 计算

问题描述 投票:0回答:2

我目前正在使用 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 标准中引用的算法之间有任何区别。

nfc crc
2个回答
4
投票

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

这是与问题的测试向量匹配的独立代码:

# 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
    的输出为大端字节序;它是小端字节序,并且在电信中必须如此才能保留 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())

在线尝试!


0
投票
function NTAG424CRC(m) {
  let c = 4294967295; // 0xffffffff
  for (let i = 0; i < m.length; i++) {
    c = c ^ m[i];
    for (let j = 0; j < 8; j++) {
      c = (c >>> 1) ^ (3988292384 & -(c & 1));   // 3988292384 === 0xEDB88320
    }
  }

  let buffer = new ArrayBuffer (4);     // 4 === length of crc32 in decimal
  let view = new DataView(buffer);
  view.setUint32(0, c, true);
  let bytes = new Uint8Array(buffer);
  return bytes;
}

let crc32Value = NTAG424CRC(
  new Uint8Array([
    0xf3, 0x84, 0x7d, 0x62, 0x77, 0x27, 0xed, 0x3b, 0xc9, 0xc4, 0xcc, 0x05,
    0x04, 0x89, 0xb9, 0x66,
  ])
);

//the result will be in decimal change them to hex
//and this works in node
© www.soinside.com 2019 - 2024. All rights reserved.