访问智能卡文件结构

时间:2014-07-03 20:47:42

标签: java filesystems smartcard apdu smartcard-reader

我正在尝试从身份证上阅读特定信息。

我想获取姓名,身份证号码,DOB等。这是一张智能卡。

我编写了一个与读卡器和卡连接的Java程序。

唯一的问题是当我想从卡上读取信息时,我不知道文件在哪个DF(专用文件)或EF(基本文件)中的确切位置。 MF固定为3F00但其他我不知道。

这是比利时身份证档案位置的一个例子:

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 };

但这与我们国家的身份证和政府没有提及卡的结构有关。有没有办法知道结构或读取整张卡而不提及具体文件?

选择文件:

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

我认为唯一的问题是:

  

IDENTITY_FILE_AID

这是整个程序代码:

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");
        }
    }
}

我遇到的问题是我不确切知道信息的保存位置。

那我该怎么办?

1 个答案:

答案 0 :(得分:0)

没有通用的方法来查找智能卡的结构/命令/文件系统布局。这通常取决于应用程序。某些身份证存在一些标准(如机读旅行证件的ICAO 9303),但国家身份证没有全球标准。因此,我建议您尝试从政府获取ID规范。