首先:
“不是”所有的 Java 卡内部都有 MF、DF 和 EF!这些词依次代表主文件、专用文件和基本文件。它们是 ISO7816 定义的智能卡系统文件 (refer to part 4 of ISO7816) 的组件,因此您的卡可能有也可能没有这个文件系统。
典型的 java 卡有一个存储,您可以在其中安装您的小程序(在成功验证之后)并注册您的小程序的名称(我们称之为 AID,代表 Applet IDentifier 和它是一个 5 到 16 字节的十六进制序列)在卡的注册表(加载/安装的小程序和包含生命周期和特权的包的表 - read Global Platform Card Spec)中。
然后:
假设您的读卡器中插入了智能卡,并连接到您的计算机。您有不同的选择来在您的计算机和卡之间进行通信。
1-您可以使用可用的工具,例如您的读者工具(几乎所有读者都有一个工具)、PyAPDUTool 等。
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- 您可以使用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- 您可以使用WinSCard 库在 C++/.Net 中编写程序(不确定)以与智能卡进行通信。
以上程序是向智能卡发送 APDU 命令的示例程序。但是这些命令本身取决于您的卡以及 [您的] 安装在卡上的小程序。
例如,假设您正在编写一个 AID = 01 02 03 04 05 00 的小程序,当它收到 00 00 00 00 00 作为 APDU 命令时返回 11 22 33 44 55。收到此回复(即11 22 33 44 55)所需的操作如下:
- 发送一个 SELECT APDU 命令,在其数据字段中包含您的小程序 AID。
- 将
00 00 00 00 00 发送到您的小程序。
- 您的小程序对上述命令的响应是预期的。
如果你的卡已经实现了ISO7816系统文件,你需要文件ID来选择它们。但命令本身是在 ISO7816-P4 中定义的。
即使您的卡没有实现 ISO7816 系统文件,您也可以编写一个小程序来像实现了 ISO7816-P 系统文件的智能卡一样运行(无论如何都不容易)。
由于 MF 的 ID 始终为3F00,尝试选择此文件,将显示您的卡是否实现了系统文件。
通常,当您的卡启动时,卡中名为 Card Manager 的强制实体会接收您的 APDU 命令。通过使用 SELECT APDU 命令,您请求卡管理器将下一个传入命令发送到选定的 APPLET