Get UID of Mifare Ultralight with SCL010

前端 未结 2 775
你的背包
你的背包 2020-12-06 07:37

I want get the UID of the Mifare Ultralight NFC tag. In Java I have this code:

TerminalFactory factory = TerminalFactory.getDefault();
List

        
相关标签:
2条回答
  • 2020-12-06 07:41
    import java.nio.ByteBuffer;
    import java.util.List;
    import javax.smartcardio.Card;
    import javax.smartcardio.CardChannel;
    import javax.smartcardio.CardException;
    import javax.smartcardio.CardTerminal;
    import javax.smartcardio.TerminalFactory;
    
    public class Read {
    
    public Read() {
    
        try {
    
            CardTerminal terminal = null;
    
            // show the list of available terminals
            TerminalFactory factory = TerminalFactory.getDefault();
            List<CardTerminal> terminals = factory.terminals().list();
            String readerName = "";
    
            for (int i = 0; i < terminals.size(); i++) {
    
                readerName = terminals.get(i).toString()
                        .substring(terminals.get(i).toString().length() - 2);
                //terminal = terminals.get(i);
    
                if (readerName.equalsIgnoreCase(" 0")) {
                    terminal = terminals.get(i);
                }
            }
    
            // Establish a connection with the card
            System.out.println("Waiting for a card..");
    
            if(terminal==null)
                return;
            terminal.waitForCardPresent(0);
    
            Card card = terminal.connect("T=0");
            CardChannel channel = card.getBasicChannel();
    
            // Start with something simple, read UID, kinda like Hello World!
            byte[] baReadUID = new byte[5];
    
            baReadUID = new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00,
                    (byte) 0x00, (byte) 0x00 };
    
            System.out.println("UID: " + send(baReadUID, channel));
            // If successfull, the output will end with 9000
    
            // OK, now, the real work
    
    
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    
    
    public String send(byte[] cmd, CardChannel channel) {
    
        String res = "";
    
        byte[] baResp = new byte[258];
        ByteBuffer bufCmd = ByteBuffer.wrap(cmd);
        ByteBuffer bufResp = ByteBuffer.wrap(baResp);
    
        // output = The length of the received response APDU
        int output = 0;
    
        try {
    
    
    output = channel.transmit(bufCmd, bufResp);
        }` catch (CardException ex) {
            ex.printStackTrace();
        }`
    
        for (int i = 0; i < output; i++) {
            res += String.format("%02X", baResp[i]);
            // The result is formatted as a hexadecimal integer
        }
    
        return res;
    }
    
    public static void main(String[] args) {
        new Read();
    }
    }
    

    After read this code For read and write purpose use bellow commands.

    And Read From page : 04 to page : 07 Command is:

    read_four_to_seven = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0x00,
                             (byte) 0x00, (byte) 0x05, (byte) 0x0D4, (byte) 0x40, (byte) 0x01,
                             (byte) 0x30, (byte) 0x04, (byte) 0x07 };
    System.out.println("Read : " + send(read_four_to_seven, channel));
    

    Write into Page 04:

    Write_Page_Four = new byte[] { (byte) 0xFF, (byte) 0x00, (byte) 0x00,
    (byte) 0x00, (byte) 0x15, (byte) 0xD4, (byte) 0x40,
    (byte) 0x01, (byte) 0xA0, (byte) 0x04, (byte) 0x4D,
    (byte) 0x65, (byte) 0x73, (byte) 0x75, (byte) 0x00,
    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
    (byte) 0x00, (byte) 0x00, (byte) 0x00 };
    System.out.println("Read : " + send(Write_Page_Four, channel));
    
    0 讨论(0)
  • 2020-12-06 08:01

    The command you are actually using is not what you might have expected.

    The correct command APDU to get the UID/serial number/enumeration identifier with this reader is:

    +------+------+------+------+------+
    | CLA  | INS  |  P1  |  P2  |  Le  |
    +------+------+------+------+------+
    | 0xFF | 0xCA | 0x00 | 0x00 | 0x00 |
    +------+------+------+------+------+
    

    However, the constructor you are using is defined as:

    public CommandAPDU(int cla, int ins, int p1, int p2, int ne);
    

    So with

    new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x00)
    

    you are creating a C-APDU with the following parameters CLA = 0xFF, INS = 0xCA, P1 = 0x00, P2 = 0x00. So far this is the same as the above APDU. But the last parameter is Ne = 0x00. Ne = 0 means that the number of expected response bytes is zero (whereas Le = 0 would mean that the number of expected response bytes is (up to) 256).

    This results in effectively creating the following Case-1 APDU:

    +------+------+------+------+
    | CLA  | INS  |  P1  |  P2  |
    +------+------+------+------+
    | 0xFF | 0xCA | 0x00 | 0x00 |
    +------+------+------+------+
    

    So at most you will get the 2-byte status word as a response (either indicating success with 0x90 0x00 or indicating an error with a status code like 0x6X 0xXX).

    So you can either use a byte array to form your APDU:

    new CommandAPDU(new byte[] { (byte)0xFF, (byte)0xCA, (byte)0x00, (byte)0x00, (byte)0x00 } )
    

    Or you can specify a proper value for Ne:

    new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 256)
    
    0 讨论(0)
提交回复
热议问题