如何使用nfcpy通过ACR122U读卡器读写MIFARE 1K Classic卡
读写MIFARE 1K Classic卡(ACR122U + nfcpy)
Hey there! I’ve worked with the ACR122U and nfcpy for MIFARE Classic cards plenty of times, so let’s break down exactly how to read and write to your MIFARE 1K card step by step.
前置准备
- 安装nfcpy: 通过pip安装库,执行命令
pip install nfcpy - 确认读卡器被识别: Linux系统下可以在终端运行
nfc-list检查ACR122U是否被检测到;Windows系统则在设备管理器中查看是否有NFC设备条目。 - 知晓卡片密钥: MIFARE 1K包含16个扇区(每个扇区分4个块),每个扇区都有密钥A和密钥B用于身份验证。大部分空白卡的默认密钥A为
0xFF0xFF0xFF0xFF0xFF0xFF,如果你的卡片是预配置的,需要获取对应扇区的正确密钥。
基础代码示例
下面是实用的读写代码片段,直接就能用。
1. 读取块数据
这个示例会连接卡片、用默认密钥A验证身份,然后读取块1(属于扇区0——注意:块0是厂商块,不要修改它)的数据。
import nfc import ndef def read_mifare_block(): # 通过USB初始化NFC读卡器 clf = nfc.ContactlessFrontend('usb') try: # 等待卡片触碰读卡器 tag = clf.connect(rdwr={'on-connect': lambda tag: False}) # 检查是否是MIFARE Classic卡 if isinstance(tag, nfc.tag.tt3.Type3Tag): print("哎呀,这不是MIFARE Classic卡——请确认你的卡片类型!") return # 定义要读取的块(块1对应地址0x01) target_block = 0x01 default_key_a = b'\xFF\xFF\xFF\xFF\xFF\xFF' # 用密钥A验证以获取块的访问权限 if tag.authenticate(target_block, default_key_a, 0): # 0表示使用密钥A # 读取16字节的块数据 block_data = tag.read(target_block) print(f"块{target_block}的原始数据: {block_data.hex()}") # 尝试解析为NDEF格式(部分卡片用这个存储标准数据) try: ndef_records = ndef.message_decoder(block_data) print("\n解析出的NDEF记录:") for record in ndef_records: print(f" - {record}") except: print("\n这个块不包含有效的NDEF数据。") else: print(f"密钥A验证失败——无法读取块{target_block}。") finally: # 务必关闭读卡器连接 clf.close() if __name__ == "__main__": read_mifare_block()
2. 写入数据到块
写入需要先完成身份验证,并且数据必须是16字节(如果内容较短,可以用空格或空字节填充)。这个示例会向块1写入一段简单的文本。
import nfc def write_mifare_block(): clf = nfc.ContactlessFrontend('usb') try: tag = clf.connect(rdwr={'on-connect': lambda tag: False}) if isinstance(tag, nfc.tag.tt3.Type3Tag): print("这不是MIFARE Classic卡——请确认使用的卡片类型正确!") return target_block = 0x01 default_key_a = b'\xFF\xFF\xFF\xFF\xFF\xFF' # 准备16字节的数据(用空格填充至满块) data_to_write = b'Hello MIFARE! ' # 先完成身份验证 if tag.authenticate(target_block, default_key_a, 0): # 向块写入数据 tag.write(target_block, data_to_write) print(f"成功写入块{target_block}!") # 读取数据验证写入结果 verified_data = tag.read(target_block) print(f"验证内容: {verified_data.decode('utf-8').strip()}") else: print(f"身份验证失败——无法写入块{target_block}。") finally: clf.close() if __name__ == "__main__": write_mifare_block()
避坑关键提示
- 密钥差异: 如果默认密钥A无效,你的卡片可能有自定义密钥。部分扇区只允许用密钥B写入,如果你有密钥B,可以尝试将
authenticate()的第三个参数改为1(表示使用密钥B)。 - 扇区尾块: 每个扇区的最后一个块(比如扇区0的块3)是扇区尾块,存储着密钥A、访问控制位和密钥B。除非你完全清楚操作后果,否则不要修改这个块——出错可能导致卡片报废。
- 访问控制位: 这些位决定了密钥A和密钥B分别允许哪些操作(读/写/验证)。如果有正确密钥但写入失败,可能是访问控制位限制了写入权限。
- Linux权限: Linux系统下可能需要root权限才能使用ACR122U。要让普通用户也能使用,可以创建udev规则:
- 创建文件
/etc/udev/rules.d/99-nfc.rules,内容如下:SUBSYSTEM=="usb", ATTRS{idVendor}=="072f", ATTRS{idProduct}=="2200", GROUP="plugdev", MODE="0666" - 重新加载udev规则:
sudo udevadm control --reload-rules && sudo udevadm trigger
- 创建文件
内容的提问来源于stack exchange,提问作者Tee
相关产品推荐
相关产品推荐

