You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求Python代码:用HID OMNIKEY 5321 CL读取Mifare DESFire卡视觉ID

读取Mifare DESFire卡面视觉ID的Python方案

问题背景

我使用HID OMNIKEY 5321 CL读卡器读取Mifare DESFire卡,已通过Python代码成功读取卡片UID(示例UID:04 11 64 FA BC 24 80),但需要读取卡面印刷的视觉ID(示例视觉ID:30307877)。

现有读取UID的代码

from smartcard.System import readers
from smartcard.util import toHexString
# 建立与读卡器的连接
reader = readers()[0]
connection = reader.createConnection()
connection.connect()
# 发送APDU命令获取卡片数据
command = [0xFF, 0xCA, 0x00, 0x00, 0x00]  # 根据需求调整命令
response, sw1, sw2 = connection.transmit(command)
# 打印响应数据
if sw1 == 0x90 and sw2 == 0x00:
    print("成功读取卡片数据:")
    print(toHexString(response))
else:
    print("读取卡片数据失败。")
# 断开与读卡器的连接
connection.disconnect()

设备及卡片规格

读卡器规格

FW : 5.20
Op Mode : ISO
Lib : 200
Por: USB
USB Serial No :  OKCM007040812072942435634869263
ITEM NO : R53210038-1
REVISION : B
VERSION INDEX: ELZ00120

Mifare DESFire卡规格

Smartcard name: MiFare DESFire 
ATR : 3B 81 80 01 80 80
UID : 04 1A 68 FA BC 24 80
Protocol: ISO 14443A  T=CL
PICCtoPCD : 424 kbps
Frequency : 13.56 Mhz
PCDtoPICC 

读取视觉ID的Python代码

卡面印刷的视觉ID通常存储在DESFire卡的制造商数据区域或自定义应用文件中,需通过DESFire原生APDU命令读取。以下是通用实现代码:

from smartcard.System import readers
from smartcard.util import toHexString

def read_desfire_visual_id():
    # 连接读卡器
    reader = readers()[0]
    connection = reader.createConnection()
    connection.connect()

    try:
        # 尝试读取制造商数据区域
        # PC/SC封装的DESFire读取制造商数据命令
        cmd_mfg_data = [0x90, 0x60, 0x00, 0x00, 0x00]
        response, sw1, sw2 = connection.transmit(cmd_mfg_data)

        if sw1 == 0x90 and sw2 == 0x00:
            print("制造商数据读取成功:")
            print(toHexString(response))
            
            # 解析视觉ID:需根据卡片实际存储位置调整字节切片
            # 示例假设视觉ID存储在响应的第4-7字节(大端字节序)
            visual_id_bytes = response[4:8]
            visual_id = int.from_bytes(visual_id_bytes, byteorder='big')
            print(f"卡面视觉ID: {visual_id}")
        else:
            # 若制造商区域读取失败,尝试读取自定义应用中的数据
            # 替换为卡片实际的应用ID(示例为0x123456)
            target_app_id = [0x12, 0x34, 0x56]
            cmd_select_app = [0x90, 0x5A, 0x00, 0x00, 0x03] + target_app_id + [0x00]
            response, sw1, sw2 = connection.transmit(cmd_select_app)
            
            if sw1 == 0x90 and sw2 == 0x00:
                # 替换为卡片实际的文件ID(示例为0x01)
                cmd_select_file = [0x90, 0xBD, 0x00, 0x01, 0x00]
                response, sw1, sw2 = connection.transmit(cmd_select_file)
                
                if sw1 == 0x90 and sw2 == 0x00:
                    # 读取文件内容
                    cmd_read_file = [0x90, 0xBD, 0x00, 0x00, 0x00]
                    response, sw1, sw2 = connection.transmit(cmd_read_file)
                    
                    if sw1 == 0x90 and sw2 == 0x00:
                        print("文件内容读取成功:")
                        print(toHexString(response))
                        # 调整字节切片匹配视觉ID存储位置
                        visual_id_bytes = response[:4]
                        visual_id = int.from_bytes(visual_id_bytes, byteorder='big')
                        print(f"卡面视觉ID: {visual_id}")
                    else:
                        print(f"读取文件失败,状态码: {hex(sw1)}{hex(sw2)[2:]}")
                else:
                    print(f"选择文件失败,状态码: {hex(sw1)}{hex(sw2)[2:]}")
            else:
                print(f"制造商区域读取失败,状态码: {hex(sw1)}{hex(sw2)[2:]}")
                print("请确认视觉ID的存储位置(制造商区域/自定义应用),并调整代码参数")
    finally:
        # 断开连接
        connection.disconnect()

if __name__ == "__main__":
    read_desfire_visual_id()

注意事项

  • 视觉ID的存储位置因制造商而异,需先打印完整的制造商数据或文件内容,定位到对应字节段后调整代码中的切片范围。
  • 若卡片启用了认证机制(如DESFire EV1/EV2),需在读取前添加密钥验证命令(如0x90, 0x0A开头的APDU)。
  • 代码中的应用ID、文件ID需替换为卡片的实际参数。

内容的提问来源于stack exchange,提问作者saad patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:34:51