简体   繁体   中英

Understanding the code behind Host Card Emulation and APDUs

I have just started making an app that uses Host Card Emulation (HCE) and I have done various bits and pieces. I need the app to make the phone behave like a card whilst another phone behaves like an NFC reader and scans it and vice versa in order to exchange a very small piece of information - an ID number.

I have done a few functional units such as the ProcessCommandApdu and defining the AID but I don't really understand how it works.

This is my code so far...

@TargetApi(19) public class MainActivity extends HostApduService {

@Override
public void onDeactivated(int reason) {

}

@Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
    String inboundApduDescription;
    byte[] responseApdu;

    if (Arrays.equals(AID_SELECT_APDU, commandApdu)) {
        inboundApduDescription = "Application selected";
        Log.i("HCEDEMO", inboundApduDescription);
        byte[] answer = new byte[2];
        answer[0] = (byte) 0x90;
        answer[1] = (byte) 0x00;
        responseApdu = answer;
        return responseApdu;

    }
    return commandApdu;
}

private static final byte[] AID_SELECT_APDU = {
        (byte) 0x00,
        (byte) 0xA4,
        (byte) 0x04,
        (byte) 0x00,
        (byte) 0x07,
        (byte) 0xF0, (byte) 0x39, (byte) 0x41, (byte) 0x48, (byte) 0x14, (byte) 0x81, (byte) 0x00,
        (byte) 0x00
};

public static void main(String[] args) throws UnsupportedEncodingException {
    TerminalFactory terminalFactory = TerminalFactory.getDefault();
    try {
        for (CardTerminal terminal : terminalFactory.terminals().list()) {
            System.out.println(terminal.getName());
            try {
                Card card = terminal.connect("*");
                CardChannel channel = card.getBasicChannel();
                System.out.println("SelectAID ");
                CommandAPDU command = new CommandAPDU(SelectAID);
                ResponseAPDU response = channel.transmit(command);
                byte recv[] = response.getBytes();
                for (int i = 0; i < recv.length; i++) {
                    System.out.print(String.format("%02X", recv[i]));
                }
                System.out.println("");
            }
            catch (CardException e){}


        }
    }
    catch(CardException e){

    }
}

}

public class ReaderActivity {
public static byte[] SelectAID = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00,
        (byte) 0x07,
        (byte) 0xF0, (byte) 0x39, (byte) 0x41, (byte) 0x48, (byte) 0x14, (byte) 0x81, (byte) 0x00, (byte)
        0x00
};

}

What do the bytes represent eg 0x00, 0xA4 and how do I convey my own information (an ID number) through the APDU?

What more do I have to add ?

I have based my code on the following tutorial https://www.slideshare.net/ChienMingChou/hce-tutorialv-v1

APDUs are specified in part 4 of the ISO 7816 standard - that's where you will find what does each byte represent (class byte, operation code, parameter bytes, etc). 0xA4 for example means SELECT command .

My recommendation is to go to the GlobalPlatform website and download the Card Specification - you'll have to register, but it is free. Chapter 11 of that Card Spec contains a lot of information about APDU encoding, the most interesting APDU commands and responses to manage cards, etc. That will help you get started and give you ideas about what APDU commands you can design for your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM