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

使用nfcpy读取非接触式信用卡公开信息的技术求助

非接触式信用卡公开信息读取问题(基于nfcpy库)

问题背景

我尝试用Python的nfcpy库读取自己非接触式信用卡的公开信息(姓名、有效期、卡号PAN、卡类型),目前仅能完成PPSE初始化并获取卡类型(如Visa Debit),无法进一步读取其他信息。

现有代码

import nfc
try:
    clf = nfc.ContactlessFrontend()
    assert clf.open('tty:USB0:pn532') is True

    tag = clf.connect(rdwr={'on-connect': lambda tag:False})
    
    cla = 0x00 # 指令类别字节
    ins = 0xA4 # 指令字节:SELECT命令
    p1 = 0x04 # 参数1:选择DF名称
    p2 = 0x00 # 参数2:返回FCI
    lc = 0x00 # 数据域长度(实际可由data自动推导)
    data = bytearray.fromhex('325041592E5359532E4444463031') # PPSE的AID:2PAY.SYS.DDF01
    le = 0x00 # 期望响应长度:返回所有可用数据

    resp = tag.send_apdu(cla,ins,p1,p2,data,check_status=False)
    print(resp)

    clf.close()
except Exception as EX:
    print(f'ERROR - {EX}')
    clf.close()

当前执行结果

代码返回带\x90\x00的bytearray(表示命令执行成功),响应中直接显示了"Visa Debit"卡类型,而非纯字节形式:

bytearray(b'o:\x84\x0e2PAY.SYS.DDF01\xa5(\xbf\x0c%a#O\x07\xa0\x00\x00\x00\x03\x10\x10P\nVisa Debit\x87\x01\x03\x9f\n\x08\x00\x01\x05\x01\x00\x00\x00\x00\x90\x00')

错误尝试

我找到Visa Debit的AID后,尝试发送以下APDU命令:

00 B2 01 02 A0 00 00 00 03 10 10 02

但仅得到错误响应:

bytearray(b'n\x00')

编辑说明

在Python中生成SFI文件定位符时,无需转换为二进制字符串,直接对字节做位运算即可(原代码存在索引错误,修正后如下):

sfi = 10  # 目标SFI编号
# 计算p2参数:SFI左移3位,加上记录控制位(4表示读取当前记录)
sfi_recs = (sfi << 3) | 4

解决建议

1. 解析PPSE响应格式

你收到的响应是BER-TLV格式,其中"Visa Debit"是卡品牌的可读文本字段,属于正常现象。从TLV结构中可提取Visa的AID:响应中的\xa0\x00\x00\x00\x03\x10\x10就是Visa的AID(长度为7字节)。

2. 修正APDU执行流程

你发送的00 B2 01 02 ...命令错误,B2是READ RECORD命令,不需要把AID放在数据域。正确流程如下:

步骤1:选择Visa的AID

发送SELECT命令激活Visa应用:

# 选择Visa AID的APDU参数
cla = 0x00
ins = 0xA4
p1 = 0x04
p2 = 0x00
data = bytearray.fromhex('A0000000031010')  # Visa的AID
le = 0x00

resp = tag.send_apdu(cla, ins, p1, p2, data, check_status=False)
print(resp)  # 成功的话末尾会有\x90\x00

步骤2:读取信用卡记录

选择成功后,发送READ RECORD命令读取公开信息。比如读取SFI 1的记录1(存储基本卡信息):

# READ RECORD命令参数
cla = 0x00
ins = 0xB2
p1 = 0x01  # 记录编号1
p2 = 0x0C  # SFI=1(左移3位得8) + 记录控制位4 = 12(0xC)
le = 0x00

resp = tag.send_apdu(cla, ins, p1, p2, le=le, check_status=False)
print(resp)

3. 解析读取到的记录

读取到的记录依然是BER-TLV格式,对应常用标签:

  • 0x5A:卡号(PAN)
  • 0x5F20:持卡人姓名
  • 0x5F24:有效期(格式为YYMM)
  • 0x9F07:卡类型标识

你可以手动解析TLV,或者使用第三方库(如ber_tlv)简化解析。

4. 关于nfcpy库的适用性

nfcpy完全适合这个场景,它支持ISO-7816标准的APDU命令交互,足以完成非接触式信用卡公开信息的读取,不需要更换其他库。


内容的提问来源于stack exchange,提问作者Jonathan Fyfe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:38:24