Pcsc -smartcard获得UID

时间:2015-01-22 16:48:00

标签: java nfc smartcard smartcard-reader pcsc

我试图从我的pcsc java代码中读取卡片UID / HCE Android设备UID。 但我收到以下错误

javax.smartcardio.CardException: sun.security.smartcardio.PCSCException: Unknown error 0x1f

虽然当我尝试获取UID时我能够获得ATS位但是我得到了这个错误。 我引用了here

中的代码

CODE

import java.io.Console;
import java.util.List;
import java.util.ListIterator;
import java.util.Scanner;

import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;

public class PCSC {

    private byte[] atr = null;
    private String protocol = null;
    private byte[] historical = null;

    public CardTerminal selectCardTerminal() {
        try {
            // show the list of available terminals
            TerminalFactory factory = TerminalFactory.getDefault();
            List<CardTerminal> terminals = factory.terminals().list();
            ListIterator<CardTerminal> terminalsIterator = terminals
                    .listIterator();
            CardTerminal terminal = null;
            CardTerminal defaultTerminal = null;
            if (terminals.size() > 1) {
                System.out
                        .println("Please choose one of these card terminals (1-"
                                + terminals.size() + "):");
                int i = 1;
                while (terminalsIterator.hasNext()) {
                    terminal = terminalsIterator.next();
                    System.out.print("[" + i + "] - " + terminal
                            + ", card present: " + terminal.isCardPresent());
                    if (i == 1) {
                        defaultTerminal = terminal;
                        System.out.println(" [default terminal]");
                    } else {
                        System.out.println();
                    }
                    i++;
                }
                Scanner in = new Scanner(System.in);
                try {
                    int option = in.nextInt();
                    terminal = terminals.get(option - 1);
                } catch (Exception e2) {
                    // System.err.println("Wrong value, selecting default terminal!");
                    terminal = defaultTerminal;

                }
                System.out.println("Selected: " + terminal.getName());
                // Console console = System.console();
                return terminal;
            }

        } catch (Exception e) {
            System.err.println("Error occured:");
            e.printStackTrace();
        }
        return null;
    }

    public String byteArrayToHexString(byte[] b) {
        StringBuffer sb = new StringBuffer(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            int v = b[i] & 0xff;
            if (v < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(v));
        }
        return sb.toString().toUpperCase();
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character
                    .digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    public Card establishConnection(CardTerminal ct) {
        this.atr = null;
        this.historical = null;
        this.protocol = null;

        System.out
                .println("To establish connection, please choose one of these protocols (1-4):");
        System.out.println("[1] - T=0");
        System.out.println("[2] - T=1");
        System.out.println("[3] - T=CL");
        System.out.println("[4] - * [default]");

        String p = "*";
        Scanner in = new Scanner(System.in);

        try {
            int option = in.nextInt();

            if (option == 1)
                p = "T=0";
            if (option == 2)
                p = "T=1";
            if (option == 3)
                p = "T=CL";
            if (option == 4)
                p = "*";
        } catch (Exception e) {
            // System.err.println("Wrong value, selecting default protocol!");
            p = "*";
        }

        System.out.println("Selected: " + p);

        Card card = null;
        try {
            card = ct.connect(p);
        } catch (CardException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
        ATR atr = card.getATR();
        System.out.println("Connected:");
        System.out.println(" - ATR:  " + byteArrayToHexString(atr.getBytes()));
        System.out.println(" - Historical: "
                + byteArrayToHexString(atr.getHistoricalBytes()));
        System.out.println(" - Protocol: " + card.getProtocol());

        this.atr = atr.getBytes();
        this.historical = atr.getHistoricalBytes();
        this.protocol = card.getProtocol();

        return card;

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        PCSC pcsc = new PCSC();
        CardTerminal ct = pcsc.selectCardTerminal();
        Card c = null;
        if (ct != null) {
            c = pcsc.establishConnection(ct);
            CardChannel cc = c.getBasicChannel();



            try {

                 ResponseAPDU answer = cc.transmit(new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x00));

                   System.out.println("answer: " + answer.toString());

            } catch (CardException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

输出

Please choose one of these card terminals (1-3):
[1] - PC/SC terminal ACS ACR1281 1S Dual Reader ICC 0, card present: false [default terminal]
[2] - PC/SC terminal ACS ACR1281 1S Dual Reader PICC 0, card present: true
[3] - PC/SC terminal ACS ACR1281 1S Dual Reader SAM 0, card present: false
2
Selected: ACS ACR1281 1S Dual Reader PICC 0
To establish connection, please choose one of these protocols (1-4):
[1] - T=0
[2] - T=1
[3] - T=CL
[4] - * [default]
4
Selected: *
Connected:
 - ATR:  3B8F8001804F0CA0000003060300030000000068
 - Historical: 804F0CA00000030603000300000000
 - Protocol: T=1
javax.smartcardio.CardException: sun.security.smartcardio.PCSCException: Unknown error 0x1f
    at sun.security.smartcardio.ChannelImpl.doTransmit(Unknown Source)
    at sun.security.smartcardio.ChannelImpl.transmit(Unknown Source)
    at myPcscGoogleCode.PCSC.main(PCSC.java:186)
Caused by: sun.security.smartcardio.PCSCException: Unknown error 0x1f
    at sun.security.smartcardio.PCSC.SCardTransmit(Native Method)
    ... 3 more

已经提到以下内容 Get UID of Mifare Ultralight with SCL010

请帮忙!

由于

1 个答案:

答案 0 :(得分:9)

我能够通过更改命令APDU找到解决方案并获取UID。 然后我将结果byte []转换为十六进制UID。

try {
                //get UID cmd apdu
                 ResponseAPDU answer = cc.transmit( new CommandAPDU(new byte[] { (byte)0xFF, (byte)0xCA, (byte)0x00, (byte)0x00, (byte)0x00 } ));

                   System.out.println("answer: " + answer.toString());

                   byte[] reponseBytesArr=answer.getBytes();

                   System.out.println("answer byte[]");
                   StringBuilder sb = new StringBuilder();

                   for(int i=0;i<reponseBytesArr.length;i++){
                       //print arr
                       byte b =reponseBytesArr[i];
                       System.out.println(b);
                       if(i<=reponseBytesArr.length-3){
                        // append uid
                       sb.append(String.format("%02X ", b));
                       }
                }    
                    System.out.println("UID: "+sb.toString()); 

输出:

Please choose one of these card terminals (1-3):
[1] - PC/SC terminal ACS ACR1281 1S Dual Reader ICC 0, card present: false [default terminal]
[2] - PC/SC terminal ACS ACR1281 1S Dual Reader PICC 0, card present: true
[3] - PC/SC terminal ACS ACR1281 1S Dual Reader SAM 0, card present: false
2
Selected: ACS ACR1281 1S Dual Reader PICC 0
To establish connection, please choose one of these protocols (1-4):
[1] - T=0
[2] - T=1
[3] - T=CL
[4] - * [default]
4
Selected: *
Connected:
-Card Class class sun.security.smartcardio.CardImpl
 - ATR:  3B8F8001804F0CA0000003060300030000000068
 - Historical: 804F0CA00000030603000300000000
 - Protocol: T=1
answer: ResponseAPDU: 9 bytes, SW=9000
answer byte[]
4
-28
-66
42
0
41
-128
-112
0
UID: 04 E4 BE 2A 00 29 80