Search code examples
javafilesystemssmartcardapdusmartcard-reader

Acessing Smart Card File Structure


I am trying to read specific information from an ID Card.

I want to get the Name, ID Number, DOB and so on. It is a smart card.

I've coded a Java program that connects with the card reader and the card also.

The only problem is when I want to read the information from the card, I don't know exactly where are the files located in which DFs (Dedicated Files)or EFs (Elementary Files). MF is fixed 3F00 but others I don't know.

This is an example for the Belgian ID card File Location:

static byte[] IDENTITY_FILE_AID = new byte[] {    
   (byte) 0x3F,// MASTER FILE, Head directory MF "3f00"   
   (byte) 0x00,    
   (byte) 0xDF,// Dedicated File, subdirectory identity DF(ID) "DF01"   
   (byte) 0x01,    
   (byte) 0x40,// Elementary File, the identity file itself EF(ID#RN) "4031"   
   (byte) 0x31 };

But this isn't work with our ID Card in our country and Government not mentioning the structure of the card. Is there any way to know the structure or to read the whole card without mentioning specific file?

The file is selected with:

CommandAPDU selectFileApdu = new CommandAPDU(    
0x00, //CLA    
0xA4, //INS   
0x08, //P1   
0x0C, //P2   
IDENTITY_FILE_AID);   

I think the only problem is the:

IDENTITY_FILE_AID

This is the whole program code:

import java.util.*;

import javax.smartcardio.*;

public class Mainn {
    static byte[] IDENTITY_FILE_AID = new byte[] {
        (byte) 0x3F,// MASTER FILE, Head directory MF "3f00"
        (byte) 0x00,
        (byte) 0xDF,// Dedicated File, subdirectory identity DF(ID) "DF01"
        (byte) 0x01,
        (byte) 0x40,// Elementary File, the identity file itself EF(ID#RN) "4031"
        (byte) 0x31
    };

    static byte FIRST_NAME_TAG = (byte) 0x08;
    static byte LAST_NAME_TAG = (byte) 0x07;
    static byte NATIONAL_NUMBER_TAG = (byte) 0x06;
    static byte BIRTH_DATE_TAG = (byte) 0x0C;

    ///////////////////////////// Let's program it now !

    public static void main(String[] args) {
        TerminalFactory factory = TerminalFactory.getDefault();
        try{
            System.out.println("First");
            List<CardTerminal> terminals = factory.terminals().list();

            System.out.println("Second");
            // get the first terminal
            // This is the device for reading the card
            CardTerminal terminal = terminals.get(0);

            System.out.println("Third");
            // establish a connection with the card
            Card card = terminal.connect("*");
            System.out.println("Fourth");
            CardChannel channel = card.getBasicChannel();
            System.out.println("Fifth");
            // SELECT FILE COMMAND
            // See BEID cardpecs v2.0 page 21
            CommandAPDU selectFileApdu = new CommandAPDU(
                                                         0x00, //CLA
                                                         0xA4, //INS
                                                         0x08, //P1
                                                         0x0C, //P2
                                                         IDENTITY_FILE_AID);

            ResponseAPDU r = channel.transmit(selectFileApdu);
            int offset = 0;
            byte[] file = new byte[4096];
            byte[] data;
            do {
                CommandAPDU readBinaryApdu = new CommandAPDU(
                                                             0x00, //CLA
                                                             0xB0, //Read binary command
                                                             offset >> 8, //OFF_H higher byte of the offset (bit 8 = 0)
                                                             offset & 0xFF, //OFF_L lower byte of the offset
                                                             0xFF); //empty
                ResponseAPDU responseApdu = channel.transmit(readBinaryApdu);
                data = responseApdu.getData();
                System.arraycopy(data, 0, file, offset, data.length);
                offset += data.length;
            }
            while (0xFF == data.length);
            card.disconnect(false);
            // locate the first name field within the identity file
            System.out.println("Sixth");
            int idx = 0;
            byte length = 0;
            while (idx < file.length) {
                byte tag = file[idx];
                idx++;
                length = file[idx];
                idx++;

                String firstName = new String(Arrays.copyOfRange(file, idx, idx + length));
                System.out.println("first name: " + firstName);
                idx += length;

            }
        }
        catch(CardException ioe) {
            System.out.println("Something Wrong With The Insertion of the reader or the card");
        }
    }
}

The problem I have is that I don't know exactly where the information is saved.

So what should I do?


Solution

  • There is no general way to find out the structure/commands/file system layout of a smartcard. This is typically application dependent. There exist some standards for certain ID cards (like ICAO 9303 for machine readable travel documents) but there is no global standard for national IDs. Therefore, I suggest that you try to get the ID specifications from your government.