import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CardTerminals;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;
@SuppressWarnings("restriction")
public class APDu {
static FileOutputStream fos = null;
private static byte[] SELECT = {
(byte) 0x00, ////CLA
(byte) 0xA4, ////INS
(byte) 0x04, ////P1
(byte) 0x00, ////P2
(byte) 0x07, ////Length of AID
(byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x34, (byte) 0x49, (byte) 0x44, (byte) 0x43};
private static byte[] select_dataSet = {
(byte) 0x00, ////CLA
(byte) 0xA4, ////INS
(byte) 0x04, ////P1
(byte) 0x00, ////P2
(byte) 0x01, ////Length of AID
(byte) 0x11 }; ///////////worked
private static byte[] read_dataSet = {
(byte) 0x00, ////CLA
(byte) 0xB0, ////INS
(byte) 0x00, ////P1
(byte) 0x00, ////P2 this is the offset
(byte) 0x00, ////
(byte) 0x00,
(byte) 0xFF
};
private static CommandAPDU SELECT_APDU = new CommandAPDU(SELECT);
private static CommandAPDU select_dataSetAPDU = new CommandAPDU(select_dataSet);
private static CommandAPDU read_dataSetAPDU = new CommandAPDU(read_dataSet);
private static CardTerminal cardTerminal = null;
private static void arrayPrint(byte[] data) {
System.out.print("{");
arrayPrintBytes(data);
System.out.print("} (");
arrayPrintHex(data);
System.out.print(")");
}
private static void arrayPrintHex(byte[] data) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < data.length; i++) {
String bs = Integer.toHexString(data[i] & 0xFF);
if (bs.length() == 1)
sb.append(0);
sb.append(bs).append(" ");
}
System.out.print( sb.toString() );
}
private static void arrayPrintBytes(byte[] data) {
for(int i=0; i < data.length; i++)
System.out.print(data[i]+ " ");
}
public static boolean sendAPDU(CardChannel ch, CommandAPDU apdu,boolean write) throws CardException {
System.out.println("sent these ::: ");arrayPrintHex(apdu.getBytes());
ResponseAPDU responseAPDU = ch.transmit(apdu);
byte[] response = responseAPDU.getBytes();
System.out.print("\n"+responseAPDU.toString()+" (Nr:"+responseAPDU.getNr() +" SW:"+responseAPDU.getSW()+" SW1:"+responseAPDU.getSW1() +" SW2:"+responseAPDU.getSW2()+")");
System.out.print("Bytes received: "); arrayPrint( responseAPDU.getBytes());
System.out.print("Data received: "); arrayPrint( responseAPDU.getData());
if(write){
}
if(write){
try {
System.out.println("\n\nbytes ::: ");arrayPrintHex(responseAPDU.getData());
fos.write(responseAPDU.getData());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//Check if response is 0x9000 (code for success)
return (response[response.length - 2] == (byte) 0x90 && response[response.length - 1] == (byte) 0x00);
}
public APDu() {
}
public static void main(String[] args) throws Exception {
File f = new File("dataBytes.dat");
fos = new FileOutputStream(f,true);
TerminalFactory tf = TerminalFactory.getDefault();
CardTerminals ct = tf.terminals();
cardTerminal = ct.list().get(0);
System.out.println("Selected terminal");
if(cardTerminal==null)
throw new Exception("ERROR: No cardterminal available to communicate.");
try {
while (cardTerminal.isCardPresent()) {
Card card = null;
if ((card = cardTerminal.connect("*")) != null){
System.out.println("Connected to card.");
} else {
System.out.println("ERROR: Failed to connect to card!");
return;
}
System.out.print("ATR: "); arrayPrint(((ATR) card.getATR()).getBytes()); System.out.println();
CardChannel ch = card.getBasicChannel();
//open session
if (sendAPDU(ch, SELECT_APDU,false)){
System.out.println("\nReceived data.");
} else {
System.out.println("\nERROR: Unable to get data!");
return;
}
//select data set
if (sendAPDU(ch, select_dataSetAPDU,false)){
System.out.println("\nReceived data.");
} else {
System.out.println("\nERROR: Unable to get data!");
return;
}
//select read data set
if (sendAPDU(ch, read_dataSetAPDU,true)){
System.out.println("\nReceived data.");
} else {
System.out.println("\nERROR: Unable to get data!");
return;
}
fos.close();
return;
}
} catch (CardException e) {
System.out.println("Error isCardPresent()" + e.getCause());
}
}
}
在上面的链接中:
左边的数据是我应该从智能卡读取的实际数据,另一边是我从卡上读取的数据。 我只能读取326字节中的255个字节::::
从00-255数据和2字节状态字
我怎样才能读取剩余的字节。
=============================================== ========================= 以下是我的代码输出:
选择的终端 连接到卡。 ATR:{59 -1 -107 0 -1 -64 10 49 -2 77 -128 49 -32 107 4 32 5 2 82 85 85 85 85 85 85 -106}(3b ff 95 00 ff c0 0a 31 fe 4d 80 31 e0 6b 04 20 05 02 52 55 55 55 55 55 55 96)
Command ::: 00 a4 04 00 07 a0 00 00 00 34 49 44 43 ---命令打开会话
ResponseAPDU:2个字节,SW = 9000(Nr:0 SW:36864 SW1:144 SW2:0)接收的字节数:{-112 0}(90 00)收到的数据:{}()
收到的数据。
command ::: 00 a4 04 00 01 11 ---命令选择标题id:11
ResponseAPDU:25个字节,SW = 9000(Nr:23 SW:36864 SW1:144 SW2:0)接收的字节数:{1 17 6 94 1 70 1 10 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 - 112 0}(01 11 06 5e 01 46 01 0a 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 00 00)收到的数据:{1 17 6 94 1 70 1 10 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0}(01 11 06 5e 01 46 01 0a 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00)
收到的数据。
command ::: 00 b0 00 00 00 00 ff ---命令读取
ResponseAPDU:257个字节,SW = 9000(Nr:255 SW:36864 SW1:144 SW2:0)
06 5e是要接收的最大数据,01 46是可用数据。我已经阅读了255个字节,我只需要读取剩余的44个字节。检索剩余字节的下一个偏移量是什么。
答案 0 :(得分:1)
扩展APDU允许以更有效的方式将大量数据发送到卡,进行适当处理并发送回终端。无需重新发出多个APDU消息来完成需要大量数据的操作,并要求开发人员对应用程序进行编码以保持跨多个APDU命令的状态,扩展APDU允许applet更有效地执行此功能。大型APDU交换。
使用this reference获取更多信息。
<强>更新强>
在本参考文献中,我们逐步编写了一个利用扩展长度的applet。请注意,applet应该实现defaultHtmlAttributesObject
接口。
此外,您可以使用javacardx.apdu.ExtendedLength
,其中XX通常是早期答案的C0 00 00 XX
。这是因为该卡正在使用SW2
协议。
例如,如果回复为T=0
,则发送61 09
,直到回复变为00 C0 00 00 09
。当然,每次你应该用之前的回复取代90 00
。
答案 1 :(得分:-1)
读取大型二进制数据&gt; 255字节,你必须实现链接协议。 请查看以下链接: