使用 Smart Card IO 时无法检索第二张卡的 ATR

Posted

技术标签:

【中文标题】使用 Smart Card IO 时无法检索第二张卡的 ATR【英文标题】:Unable to retrieve the ATR of second card when using Smart Card IO 【发布时间】:2015-04-04 20:09:17 【问题描述】:

在某些背景下,我使用了 PN532 用户手册中指定的In_List_Passive_Target 命令来检索终端字段中所有卡的 UID。我还使用 ACR122U 的伪命令FF 00 00 00 04 将这些命令发送到 PN532。

>>  FF 00 00 00 04 D4 4A 01 00           # In_List_Passive_Target (1)
<<  D5 4B 01 01 00 04 08 04 3E 58 A7 D1  # Response including UID (1)
>>  FF 00 00 00 04 D4 4A 01 00           # In_List_Passive_Target (2)
<<  D5 4B 01 01 00 04 08 04 9E 69 A7 D1  # Response including UID (2)
>>  FF 00 00 00 04 D4 4A 01 00           # In_List_Passive_Target (3)
<<  D5 4B 00                             # No more cards in field (3)

既然我已经这样做了,我想一一选择这些。我可以通过在完成后暂停一张卡 (In_Deselect) 来做到这一点,然后使用带有其 UID 的 In_List_Passive_Target 命令选择下一张卡。

但是,每次我选择一张卡片时,我都想知道它返回的 ATR。事实证明,使用 Java Smart Card IO API 很难做到这一点,因为终端创建的卡对象始终是同一张卡(因此返回相同的 ATR),即使我断开卡然后创建新卡也是如此。考虑到如果我通过 PN532 终端命令In_Data_Exchange 与卡通信,这很奇怪,它是正确的不同卡(不是通过 Card 对象可访问的旧卡)。我需要 ATR 能够检测它是哪种类型的卡(Mifare Classic、Desfire、Ultralight 等)

这是我为收集卡片创建的函数:

public static void getCardsInField()
    
        cardList = new ArrayList<AbstractCard>();
        Boolean loop = true;

        // Card already connected to the terminal
        byte[] firstCardUID = transmitADPUCommand(GET_ADDRESS);
        MifareClassic firstCard = new MifareClassic(cardChannel, firstCardUID);
        cardList.add(firstCard);

        System.out.println(firstCard);
        System.out.println(readable(card.getATR().getBytes()));

        while(loop)
        
            byte[] inDeselectResponse = transmitADPUCommand(IN_DESELECT); // Deselect current card
            byte[] inListPassiveTargetsResponse = transmitADPUCommand(IN_LIST_PASSIVE_TARGETS); // Select a new card

            System.out.println(">>  " + readable(IN_LIST_PASSIVE_TARGETS));
            System.out.println("<<  " + readable(inListPassiveTargetsResponse));

            // Trying to create a new card object for new card
            try
            
                card.disconnect(true);
                card = cardTerminal.connect("*");
                cardChannel = card.getBasicChannel();
            
            catch (CardException e)
            
                e.printStackTrace();
            

            if (Arrays.equals(inListPassiveTargetsResponse, IN_LIST_PASSIVE_TARGET_RESPONSE_NO_TARGETS)) // no more targets
            
                loop = false;
            
            else
            
                byte[] loopCardUID = extractUID(inListPassiveTargetsResponse);
                MifareClassic loopCard = new MifareClassic(cardChannel, loopCardUID);
                cardList.add(loopCard);

                System.out.println(loopCard);
                System.out.println(readable(card.getATR().getBytes())); // this should be different ATR but it is the old cards atr
            
        
    

【问题讨论】:

请问UID和ATR和ATS有什么区别? 【参考方案1】:

非接触式卡片没有 ATR(重置答案)。 ATR 仅由接触卡生成(ISO/IEC 7816-3 响应取消置位复位引脚)。此外,PC/SC 模拟非接触式卡的 ATR(基于卡的某些参数),因为 PC/SC 主要是为接触式卡设计的,因此,PC/SC API 期望 ATR 可用。

非接触式卡片具有其他值。例如,基于 ISO/IEC 14443 Type A 的卡具有 ATQA (SENS_RES)、SAK (SEL_RES)、UID (NFCID1) 和可能的 ATS(接近于 ATR)。基于 ISO/IEC 14443 B 类的非接触式卡具有相似的值。

您将获得识别卡类型以响应 InListPassiveTarget 命令所需的所有信息:

Card 1: D5 4B 01 01 00 04 08 04 3E 58 A7 D1
Card 2: D5 4B 01 01 00 04 08 04 9E 69 A7 D1

对于卡 1,此数据解码为:

ATQA (SENS_RES) = 00 04 SAK (SEL_RES) = 08 UID (NFCID1) = 3E 58 A7 D1 ATS = 无

对于卡 2,此数据解码为:

ATQA (SENS_RES) = 00 04 SAK (SEL_RES) = 08 UID (NFCID1) = 9E 69 A7 D1 ATS = 无

因此,两张卡的 ATQA = 00 04 和 SAK = 08,这意味着它们很可能是 MIFARE Classic 1K 或 MIFARE Plus。

请参阅MIFARE Type Identification Procedure,了解用于识别 NXP 的 ISO/IEC 14443 A 型卡的完整值列表。

【讨论】:

以上是关于使用 Smart Card IO 时无法检索第二张卡的 ATR的主要内容,如果未能解决你的问题,请参考以下文章

如何使用smart card reader智能卡读卡器

电脑开机弹出smart card reader starter

Smart Card Filesystem

使卡片列中的第二张卡片填充所有剩余宽度

Smart Card(windows)

经验停止Smart Card服务