简体   繁体   English

如何使用java从智能卡读取文件

[英]How to read file from smart card using java

I am new in smart card technology. 我是智能卡技术的新手。 I want to read file from smart card. 我想从智能卡读取文件。 I am using javax.smartcardio to read value. 我正在使用javax.smartcardio来读取值。 I developed some code to connecting system to card (That's work fine). 我开发了一些代码来连接系统到卡(这很好)。 I have card ATR and other detail also. 我也有卡ATR和其他细节。 But not getting proper help for APDU command for communication with Smart card. 但没有得到适当的APDU命令帮助与智能卡通信。 Stuck in APDU command. 卡在APDU命令中。

First of all: 首先:

"Not" all Java cards have MF , DF and EF inside! “不是”所有Java卡都有MFDFEF These words stands for Master File , Dedicated File and Elementary File in order. 这些单词依次代表主文件专用文件基本文件 They are components of an ISO7816-defined system file for smart card ( refer to part 4 of ISO7816 ), so your card maybe or maybe not have this file system. 它们是ISO7816定义的智能卡系统文件的组件( 参见ISO7816的第4部分 ),因此您的卡可能有也可能没有此文件系统。

Typical java cards have a storage that you can install your applets in it (after a successful authentication for sure) and register name of your applet (we call it AID, that stands for Applet IDentifier and it is a 5 to 16 byte hexadecimal sequence) in the card's registry table (a table of loaded/installed applets and packages that contain life-cycles and priviledges too - read Global Platform Card Spec ). 典型的Java卡有一个存储器,您可以在其中安装您的applet(在成功验证之后)并注册您的applet的名称(我们称之为AID,代表Applet IDentifier ,它是一个5到16字节的十六进制序列)在卡的注册表中(加载/安装的applet和包含生命周期和特权的包的表 - 阅读全球平台卡规范 )。

And then: 然后:

Let assume that you have a smart card inserted in your card reader that is connected to your computer. 假设您的读卡器中插有智能卡,该智能卡已连接到您的计算机。 You have different options to have a communication between your computer and the card. 您可以使用不同的选项在计算机和卡之间进行通信。

1-You can use available tools such as your reader's tool (almost all readers have one tool), PyAPDUTool , etc. 1 - 您可以使用可用的工具,例如您的读者工具(几乎所有读者都有一个工具), PyAPDUTool等。

2-You can use Javax.smartcardio library for writing your Java program to communicate with smart cards: 2 - 您可以使用Javax.smartcardio库编写Java程序以与智能卡通信:

import java.util.List;
import java.util.Scanner;
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;
import javax.xml.bind.DatatypeConverter;

public class TestPCSC {

    public static void main(String[] args) throws CardException {

        TerminalFactory tf = TerminalFactory.getDefault();
        List< CardTerminal> terminals = tf.terminals().list();
        System.out.println("Available Readers:");
        System.out.println(terminals + "\n");

        Scanner scanner = new Scanner(System.in);
        System.out.print("Which reader do you want to send your commands to? (0 or 1 or ...): ");
        String input = scanner.nextLine();
        int readerNum = Integer.parseInt(input);
        CardTerminal cardTerminal = (CardTerminal) terminals.get(readerNum);
        Card connection = cardTerminal.connect("DIRECT");
        CardChannel cardChannel = connection.getBasicChannel();

        System.out.println("Write your commands in Hex form, without '0x' or Space charaters.");
        System.out.println("\n---------------------------------------------------");
        System.out.println("Pseudo-APDU Mode:");
        System.out.println("---------------------------------------------------");
        while (true) {
            System.out.println("Pseudo-APDU command: (Enter 0 to send APDU command)");
            String cmd = scanner.nextLine();
            if (cmd.equals("0")) {
                break;
            }
            System.out.println("Command  : " + cmd);
            byte[] cmdArray = hexStringToByteArray(cmd);
            byte[] resp = connection.transmitControlCommand(CONTROL_CODE(), cmdArray);
            String hex = DatatypeConverter.printHexBinary(resp);
            System.out.println("Response : " + hex + "\n");
        }

        System.out.println("\n---------------------------------------------------");
        System.out.println("APDU Mode:");
        System.out.println("---------------------------------------------------");

        while (true) {
            System.out.println("APDU command: (Enter 0 to exit)");
            String cmd = scanner.nextLine();
            if (cmd.equals("0")) {
                break;
            }
            System.out.println("Command  : " + cmd);
            byte[] cmdArray = hexStringToByteArray(cmd);
            ResponseAPDU resp = cardChannel.transmit(new CommandAPDU(cmdArray));
            byte[] respB = resp.getBytes();
            String hex = DatatypeConverter.printHexBinary(respB);
            System.out.println("Response : " + hex + "\n");
        }

        connection.disconnect(true);

    }

    public static int CONTROL_CODE() {
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.indexOf("windows") > -1) {
            /* Value used by both MS' CCID driver and SpringCard's CCID driver */
            return (0x31 << 16 | 3500 << 2);
        } else {
            /* Value used by PCSC-Lite */
            return 0x42000000 + 1;
        }

    }

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

}

3- You can use PySCard library to write your Python program to communicate with smart cards: 3-您可以使用PySCard库编写Python程序以与智能卡通信:

#Importing required modules.
import sys
import time
#--- You may need to change the following "line" based on your pyScard library installation path
sys.path.append("D:\\PythonX\\Lib\\site-packages")
from smartcard.scard import *
import smartcard.util
from smartcard.System import readers


#---This is the list of commands that we want to send device
cmds =[[,0xFF,0x69,0x44,0x42,0x05,0x68,0x92,0x00,0x04,0x00],]


#--- Let's to make a connection to the card reader
r=readers()
print "Available Readers :",r
print
target_reader = input("--- Select Reader (0, 1 , ...): ")
print

while(True):
    try:
        print "Using :",r[target_reader]
        reader = r[target_reader]
        connection=reader.createConnection()
        connection.connect()
        break
    except:
        print "--- Exception occured! (Wrong reader or No card present)"
        ans = raw_input("--- Try again? (0:Exit/1:Again/2:Change Reader)")
        if int(ans)==0:
            exit()
        elif int(ans)==2:
            target_reader = input("Select Reader (0, 1 , ...): ")

#--- An struct for APDU responses consist of Data, SW1 and SW2
class stru:
    def __init__(self):
        self.data = list()
        self.sw1 = 0
        self.sw2 = 0

resp = stru()

def send(cmds):
    for cmd in cmds:

        #--- Following 5 line added to have a good format of command in the output.
        temp = stru() ;
        temp.data[:]=cmd[:]
        temp.sw1=12
        temp.sw2=32
        modifyFormat(temp)
        print "req: ", temp.data

        resp.data,resp.sw1,resp.sw2 = connection.transmit(cmd)
        modifyFormat(resp)
        printResponse(resp)

def modifyFormat(resp):
    resp.sw1=hex(resp.sw1)
    resp.sw2=hex(resp.sw2)   
    if (len(resp.sw2)<4):
        resp.sw2=resp.sw2[0:2]+'0'+resp.sw2[2]
    for i in range(0,len(resp.data)):
        resp.data[i]=hex(resp.data[i])
        if (len(resp.data[i])<4):
            resp.data[i]=resp.data[i][0:2]+'0'+resp.data[i][2]

def printResponse(resp):
    print "res: ", resp.data,resp.sw1,resp.sw2


send(cmds)
connection.disconnect()

4- You can use WinSCard library to write your program in C++/.Net (Not sure) to communicate with smart cards. 4-您可以使用WinSCard库以C ++ / .Net编写程序(不确定)与智能卡通信。

Above programs are sample programs to send APDU commands to smart cards. 以上程序是将APDU命令发送到智能卡的示例程序。 But the commands themselve are depend on your card and the applets that [your] are installed on it. 但是它们的命令取决于你的卡和你的[你]安装的小程序。

For example let assume that you are write an applet with AID = 01 02 03 04 05 00 that returns 11 22 33 44 55 when it receive 00 00 00 00 00 as APDU command. 例如,假设您正在编写AID = 01 02 03 04 05 00的applet,当它接收00 00 00 00 00作为APDU命令时返回11 22 33 44 55 What you need to do to receive this response (ie 11 22 33 44 55 ) is as below: 您需要做什么才能收到此回复(即11 22 33 44 55 )如下:

  1. Send a SELECT APDU command with you applet's AID in its data field. 在其数据字段中使用applet的AID发送SELECT APDU命令。
  2. Sending 00 00 00 00 00 to your applet. 00 00 00 00 00发送到您的小程序。
  3. Your applet response to the above command with expected answer. 您的applet响应上述命令并带有预期答案。

If your card have been implemented ISO7816 system file, you need ID of files to select them. 如果您的卡已经实现了ISO7816系统文件,则需要文件ID才能选择它们。 but the commands themselves are defined in ISO7816-P4. 但命令本身在ISO7816-P4中定义。

Even if your cards doesn't implemented ISO7816 system file, you can write an applet to act like a ISO7816-P system file implemented smart card (Not easy anyway). 即使您的卡没有实现ISO7816系统文件,您也可以编写一个小程序,就像ISO7816-P系统文件实现的智能卡一样(不管怎么说都不容易)。

As the ID of MF is 3F00 always, trying to select this file, will show you if your card implemented the system-file or not. 由于MF的ID总是3F00 ,尝试选择此文件,将显示您的卡是否实现了系统文件。

Typically when your card powers on, a mandatory entity in the card named Card Manager, receive your APDU commands. 通常,当您的卡启动时,名为Card Manager的卡中的强制实体会收到您的APDU命令。 By using SELECT APDU command, you request the card manager to send next incoming commands to the selected APPLET 通过使用SELECT APDU命令,您请求卡管理器将下一个传入命令发送到所选的APPLET

There are various kind of smart card in the market, Each are using different structure to keeping data inside. 市场上有各种各样的智能卡,每种都使用不同的结构来保存数据。 File structure is defined in I SO 7816-4: Organization, security and commands for interchange 文件结构在I SO 7816-4中定义:组织,安全性和交换命令

You can see link1 and Link2 for more about smart card file structure. 有关智能卡文件结构的更多信息,请参阅link1Link2

It is the choice of card personlisation entity whether they use this file structure or not to keeping data inside chip. 卡片人员实体的选择是否使用这种文件结构来保持芯片内的数据。 Indian standard SCOSTA is fully complient with ISO 7816 standard , it means any product that is SCOSTA complient will use the structure defined in ISO 7816 -4 ( MF, DF, EF). 印度标准SCOSTA完全符合ISO 7816标准,这意味着任何SCOSTA complient产品都将使用ISO 7816 -4(MF,DF,EF)中定义的结构。

Here you should know the structure of the card before sending any command to it. 在发送任何命令之前,您应该知道卡的结构。 Like Select MF -> Select DF -> Select EF -> Read Record Command. 如选择MF - >选择DF - >选择EF - >读取记录命令。

In case of java card ( smart card) , there are not always File Structure created to keeping data, it can be use arrays [ie Persistent memory] and assign values to it during operations. 对于java卡(智能卡),并不总是创建文件结构来保存数据,它可以使用数组[即持久存储器]并在操作期间为其赋值。 This value reside in smart card lifetime. 此值驻留在智能卡生命周期中。 Want to get the value just send an appropriate defined command and card will return you the value from the array. 想要获取值只是发送一个适当的定义命令,卡将返回数组中的值。 that is all. 就这些。

It means we can say all smart card does not follow File structure rule 这意味着我们可以说所有智能卡都不遵循文件结构规则

To read any smart card there are some pre-defined rules , If card is structure wise, we should know the structure otherwise we can get Error status word . 要读取任何智能卡,有一些预先定义的规则,如果卡是结构明智的,我们应该知道结构,否则我们可以得到错误状态字

If talk about command , it is also defined Here -Smart Card Command Rules you can read here to enhance your knowledge about smart card commands so that you could send right command. 如果谈论命令,它也被定义这里 - 智能卡命令规则,您可以在这里阅读,以增强您对智能卡命令的了解,以便您可以发送正确的命令。

But not getting proper help for APDU command for communication with Smart card. Stuck in APDU command.

Here you should know more about Smart card you are using before sending any command to it. 在发送任何命令之前,您应该了解有关您正在使用的智能卡的更多信息。 It is good to share Command Response to check the exact issue. 分享命令响应以检查确切问题是很好的。 javax.smartcardio is very good API to communicate with smart card, also there any various example already shared that helps you to write code to access any smart card. javax.smartcardio是与智能卡通信的非常好的API,也有任何已经共享的各种示例,可以帮助您编写代码来访问任何智能卡。

Hope after knowing the deep detail of the smart card you are using and once you build appropriate command you will not get any error. 希望在了解您正在使用的智能卡的深层细节后,一旦您构建了适当的命令,您将不会收到任何错误。 Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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