从零到一:手把手教你用Python玩转ISO14443读卡(附完整代码与调试技巧)
从零到一手把手教你用Python玩转ISO14443读卡附完整代码与调试技巧在物联网和嵌入式开发领域与智能卡进行通信是一项基础但关键的技能。ISO14443作为近场通信NFC的主流标准之一广泛应用于门禁系统、支付终端和各种身份认证场景。本文将带你从硬件选型开始一步步实现用Python控制读卡器与ISO14443卡片交互的全过程。1. 硬件准备与环境搭建1.1 读卡器选型与连接市面上支持ISO14443协议的读卡器种类繁多对于Python开发者来说ACR122U是一个性价比高且兼容性好的选择。这款读卡器通过USB接口与计算机连接支持Type A和Type B两种卡片类型。连接读卡器时需要注意确保安装了官方驱动程序在Linux系统下可能需要配置udev规则Windows系统通常即插即用# 检查读卡器是否被系统识别 import serial.tools.list_ports ports serial.tools.list_ports.comports() for port in ports: if ACS in port.manufacturer: print(f找到读卡器: {port.device})1.2 Python库安装我们将使用pyscard这个强大的库来实现与智能卡的通信。安装方法如下pip install pyscard对于需要更底层控制的场景可以额外安装libnfc的Python绑定pip install python-libnfc2. 基础通信流程实现2.1 建立与读卡器的连接首先需要初始化读卡器并建立连接from smartcard.System import readers from smartcard.util import toHexString # 获取可用读卡器列表 reader_list readers() if not reader_list: raise Exception(未检测到读卡器) # 选择第一个读卡器 reader reader_list[0] print(f使用读卡器: {reader}) # 建立连接 connection reader.createConnection() connection.connect()2.2 发送APDU指令APDUApplication Protocol Data Unit是与智能卡通信的基本单位。一个典型的APDU指令包含4个部分部分说明长度CLA指令类别1字节INS指令代码1字节P1参数11字节P2参数21字节Lc数据长度0-3字节Data数据字段变长Le期望响应长度0-3字节发送APDU指令的Python代码示例def send_apdu(connection, cla, ins, p1, p2, dataNone, le0): apdu [cla, ins, p1, p2] if data: apdu.append(len(data)) apdu.extend(data) if le 0: apdu.append(le) response, sw1, sw2 connection.transmit(apdu) return response, (sw1 8) | sw2 # 示例获取卡片UID response, status send_apdu(connection, 0xFF, 0xCA, 0x00, 0x00, le0) print(f卡片UID: {toHexString(response)}) print(f状态字: {hex(status)})3. 完整读卡流程实现3.1 寻卡与防碰撞ISO14443通信的第一步是寻卡和防碰撞处理。以下是完整的流程实现def find_card(connection): # 发送REQA指令 response, status send_apdu(connection, 0x26, 0x00, 0x00, 0x00, le2) if status ! 0x9000: raise Exception(寻卡失败) # 防碰撞处理 response, status send_apdu(connection, 0x93, 0x20, 0x00, 0x00, le16) if status ! 0x9000: raise Exception(防碰撞失败) # 提取UID uid response[:-1] # 最后一位是校验位 print(f发现卡片UID: {toHexString(uid)}) return uid3.2 选卡与建立通信获取UID后需要进行选卡操作def select_card(connection, uid): # 构造选卡指令 select_apdu [0x93, 0x70] uid [0x00] * (16 - len(uid)) # 发送选卡指令 response, status send_apdu(connection, 0xFF, 0x00, 0x00, 0x00, dataselect_apdu) if status ! 0x9000: raise Exception(选卡失败) # 检查SAK sak response[0] print(f选卡成功SAK: {hex(sak)}) return sak4. 高级功能与调试技巧4.1 数据块读写操作对于支持数据存储的卡片我们可以进行读写操作def read_block(connection, block_num): # 构造读块指令 read_apdu [0xFF, 0xB0, 0x00, block_num, 0x10] # 发送指令 response, status send_apdu(connection, *read_apdu) if status ! 0x9000: raise Exception(f读取块{block_num}失败) return response def write_block(connection, block_num, data): # 检查数据长度 if len(data) ! 16: raise Exception(数据长度必须为16字节) # 构造写块指令 write_apdu [0xFF, 0xD6, 0x00, block_num, 0x10] data # 发送指令 _, status send_apdu(connection, *write_apdu) if status ! 0x9000: raise Exception(f写入块{block_num}失败) print(f块{block_num}写入成功)4.2 常见问题排查在实际开发中你可能会遇到以下问题卡片无响应检查读卡器是否正常工作确认卡片类型与读卡器兼容尝试调整卡片与读卡器的距离防碰撞失败确保读卡区域只有一张卡片检查UID读取是否正确尝试重新初始化连接APDU指令执行失败确认指令格式正确检查卡片是否支持该指令验证卡片是否处于正确状态4.3 使用Wireshark分析通信对于复杂的调试场景可以使用Wireshark捕获和分析通信数据安装libpcap和Wireshark配置Wireshark捕获USB流量过滤nfc或ccid协议数据# 在Linux上安装必要组件 sudo apt install wireshark libpcap-dev5. 项目实战门禁系统模拟让我们将这些知识应用到一个实际项目中——模拟简单的门禁系统class AccessControlSystem: def __init__(self): self.authorized_cards { A1B2C3D4: 管理员, E5F6G7H8: 普通用户 } def check_access(self, uid_hex): uid_str .join([f{x:02X} for x in uid_hex]) if uid_str in self.authorized_cards: print(f欢迎{self.authorized_cards[uid_str]}) return True else: print(未授权的卡片) return False # 使用示例 acs AccessControlSystem() uid find_card(connection) acs.check_access(uid)这个简单的实现展示了如何将ISO14443读卡功能集成到实际应用中。你可以进一步扩展它比如添加日志记录、多权限管理等功能。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2504633.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!