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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36693453/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 01:46:23  来源:igfitidea点击:

How to read file from smart card using java

javasmartcardjavacardapdu

提问by Krunal Indrodiya

I am new in smart card technology. I want to read file from smart card. I am using javax.smartcardio to read value. I developed some code to connecting system to card (That's work fine). I have card ATR and other detail also. But not getting proper help for APDU command for communication with Smart card. Stuck in APDU command.

我是智能卡技术的新手。我想从智能卡读取文件。我正在使用 javax.smartcardio 读取值。我开发了一些代码来将系统连接到卡(这很好用)。我也有卡片 ATR 和其他细节。但是没有得到与智能卡通信的 APDU 命令的适当帮助。卡在 APDU 命令中。

回答by Abraham

First of all:

首先:

"Not" all Java cards have MF, DFand EFinside! These words stands for Master File, Dedicated Fileand Elementary Filein 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.

“不是”所有 Java 卡都有MF,DFEF里面!这些词依次代表主文件专用文件基本文件。它们是用于智能卡的 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 IDentifierand 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卡有一个存储空间,你可以在其中安装你的小程序(在成功认证之后)和你的小程序的注册名(我们称之为AID,它代表Applet IDentifier,它是一个5到16字节的十六进制序列)在卡的注册表中(包含生命周期和特权的加载/安装的小程序和包的表 -阅读 Global Platform Card Spec)。

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.smartcardiolibrary 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 PySCardlibrary 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 WinSCardlibrary 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. But the commands themselve are depend on your card and the applets that [your] are installed on it.

以上程序是向智能卡发送 APDU 命令的示例程序。但是命令本身取决于您的卡和 [您的] 安装在其上的小程序。

For example let assume that you are write an applet with AID = 01 02 03 04 05 00that returns 11 22 33 44 55when it receive 00 00 00 00 00as APDU command. What you need to do to receive this response (i.e. 11 22 33 44 55) is as below:

例如,假设您正在编写一个带有 AID = 的小程序,当它作为 APDU 命令接收时01 02 03 04 05 00返回。您需要做什么才能收到此回复(即)如下:11 22 33 44 5500 00 00 00 0011 22 33 44 55

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

If your card have been implemented ISO7816 system file, you need ID of files to select them. but the commands themselves are defined in ISO7816-P4.

如果您的卡已执行ISO7816 系统文件,则需要文件ID 来选择它们。但命令本身是在 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 3F00always, trying to select this file, will show you if your card implemented the system-file or not.

由于 MF 的 ID3F00始终是,尝试选择此文件,将显示您的卡是否实现了系统文件。

Typically when your card powers on, a mandatory entity in the card named Card Manager, receive your APDU commands. By using SELECT APDU command, you request the card manager to send next incoming commands to the selected APPLET

通常,当您的卡通电时,卡中名为 Card Manager 的强制实体会接收您的 APDU 命令。通过使用 SELECT APDU 命令,您请求卡管理器将下一个传入命令发送到选定的 APPLET

回答by Arjun

There are various kind of smart card in the market, Each are using different structure to keeping data inside. File structure is defined in ISO 7816-4: Organization, security and commands for interchange

市场上有各种各样的智能卡,每一种都使用不同的结构来保存数据。文件结构在ISO 7816-4:交换的组织、安全和命令中定义

You can see link1and Link2for more about smart card file structure.

你可以看到链路1链路2的有关智能卡的文件结构。

It is the choice of card personlisation entity whether they use this file structure or not to keeping data inside chip. Indian standard SCOSTAis 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标准的产品都将使用 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 [i.e. Persistent memory] and assign values to it during operations. 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.

在java卡(智能卡)的情况下,并不总是创建文件结构来保存数据,它可以使用数组[即持久内存]并在操作期间为其赋值。该值存在于智能卡生命周期中。想要获取值只需发送一个适当的定义命令,卡将从数组中返回值。就这些。

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 Rulesyou 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.smartcardiois very good API to communicate with smart card, also there any various example already sharedthat 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.

希望在了解您正在使用的智能卡的详细信息后,一旦您构建了适当的命令,您就不会收到任何错误。希望能帮助到你。