无法使用 APDU 命令验证智能卡 PIN

Posted

技术标签:

【中文标题】无法使用 APDU 命令验证智能卡 PIN【英文标题】:Cant verify smart card PIN using APDU command 【发布时间】:2016-05-27 07:56:17 【问题描述】:

我正在使用 Java javax.smartcard 库从智能卡(SIM 卡)中读取数据。但我无法让我的代码验证我的 PIN。这是我的代码:

public class CopyOfCardReader 

public static final CommandAPDU SELECT_FILE_EEEE = new CommandAPDU(new byte[]  0x00, (byte) 0xA4, 0x01, 0x0C, 0x02, (byte) 0xEE, (byte) 0xEE );
public static final CommandAPDU SELECT_MASTER_FILE = new CommandAPDU(new byte[]  0x00, (byte) 0xA4, 0x00, 0x0C );
public static final CommandAPDU DISABLE_PIN = new CommandAPDU(new byte[]  0x00, (byte) 0x26, 0x00, 0x00 );

public static void main(String[] args) 

    try 

        TerminalFactory factory = TerminalFactory.getDefault();
        List<CardTerminal> terminals = null;

        terminals = factory.terminals().list();

        System.out.println("Terminals: " + terminals);
        CardTerminal terminal = terminals.get(0);
        Card card = terminal.connect("T=0");
        System.out.println("card: " + card);
        ATR atr = card.getATR();
        System.out.print("ATR: ");

        for (byte b : atr.getBytes()) 
            System.out.print(b);
        
        System.out.println();
        CardChannel channel = card.getBasicChannel();


        byte[] pin = "1234".getBytes();
        byte arg0 = (byte) 0x00;
        byte arg1 = (byte) 0x20;
        byte arg2 = (byte) 0x00;
        byte arg3 = (byte) 0x01;
        CommandAPDU command = new CommandAPDU(arg0, arg1, arg2, arg3, pin);
        ResponseAPDU request = channel.transmit(command);
        System.out.println("answer pin verify request: " + request.toString()); // response

        ResponseAPDU rmaster = channel.transmit(SELECT_MASTER_FILE);
        System.out.println("answer rmaster file: " + rmaster.toString()); // response
        System.out.println();

        ResponseAPDU rPinDiable = channel.transmit(new CommandAPDU(new byte[]  (byte) 0x00, (byte) 0x26, 0x00, 0x00 ));
        System.out.println("answer DISABLE PIN: " + rPinDiable.toString()); // response

        ResponseAPDU rverify2 = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, 0x01, new byte[]  0x31, 0x32, 0x33, 0x34, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF ));
        System.out.println("answer rverify2 pin2: " + rverify2.toString()); // response

        byte[] pin2 = "1234".getBytes();
        byte arg02 = (byte) 0x01;
        byte arg12 = (byte) 0x26;
        byte arg22 = (byte) 0x00;
        byte arg32 = (byte) 0x01;
        CommandAPDU command2 = new CommandAPDU(arg02, arg12, arg22, arg32, pin2);
        ResponseAPDU request2 = channel.transmit(command2);
        System.out.println("answer pin disable request: " + request2.toString()); // response

        byte[] baReadUID = new byte[5];
        baReadUID = new byte[]  (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 ;
        command = new CommandAPDU(baReadUID);
        ResponseAPDU r = channel.transmit(new CommandAPDU(new byte[]  0X00, (byte) 0XA4, 0X00, 0X00, 0X02, 0X3F, 0X00 ));
        System.out.println("answer r UID: " + r.toString()); // response
        System.out.print("UUID: ");
        for (byte b : r.getData()) 
            System.out.print(b); // response
        
        System.out.println();

        card.disconnect(false);
     catch (Exception e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

下面是程序输出:

Terminals: [PC/SC terminal Gemalto USB SmartCard Reader 0]
card: PC/SC card in Gemalto USB SmartCard Reader 0, protocol T=0, state OK
ATR: 5959-106064-126-1110036-155151-1120
answer pin verify request: ResponseAPDU: 2 bytes, SW=6708
answer rmaster file: ResponseAPDU: 2 bytes, SW=9000

answer DISABLE PIN: ResponseAPDU: 2 bytes, SW=6708
answer rverify2 pin2: ResponseAPDU: 2 bytes, SW=6a88
answer pin disable request: ResponseAPDU: 2 bytes, SW=6708
answer r UID: ResponseAPDU: 37 bytes, SW=9000
UUID: 9833-126212033-1252630-917-1281113-125236-15-11815-11731585-1-586-11210-12511

读取主文件和 UUID 成功,但所有其他指令均失败。有人知道我的代码有什么问题吗?请帮忙。

【问题讨论】:

您的 AID 似乎有误...6A82 表示“找不到应用程序”。 好的,我删除了销售应用程序的命令。除此之外,为什么我的 PIN 验证不起作用?为什么我收到错误 6708“长度不正确”? 【参考方案1】:

您绝对应该阅读GMS 11.11。

关于 VERIFY 部分,请尝试:

byte[] pin =  (byte)0x31, (byte)0x32, (byte)0x33, (byte)0x34, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF;

因为 PIN 长 8 个字节,较短的值用 0xFF 填充(0x310x320x33...字节表示 ASCII 字符 '1''2''3'。 ..)。

这就是67XX 状态字的含义(在这种情况下,参数P3 保持长度不正确)。有关您可能遇到的状态代码,请参阅第 9.4 节。

一些随机笔记:

您的 APDU 命令应将 CLA 字节设置为 0xA0(即第一个字节 -- arg0 一个)。

您的大多数其他命令都很奇怪——我建议遵循 GSM 11.11。

考虑用逗号分隔打印的字节(您现在得到的内容不可读)。

请注意,如此激烈的研究可能会损坏您的卡。

祝你好运!

【讨论】:

以上是关于无法使用 APDU 命令验证智能卡 PIN的主要内容,如果未能解决你的问题,请参考以下文章

APDU 命令将更改的 PIN 写入卡

使用 smartcardio 签署文件

APDU 命令异步调用

在未连接智能卡的情况下发送带有 winscard.dll (PC/SC) 的 APDU

无法使用 nfc_initiator_transceive_bytes() 使用 libnfc 发​​送大型 APDU 命令

APDU 命令获取智能卡的序列号