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());
}
}
}
In the above link :
the data on the left is the actual data which im supposed to read from the smartcard and the other side one is the data which i read from the card. im able to read only 255 bytes out of 326 bytes ::::
from 00-255 data and 2 bytes status word
how can i read the remaining bytes.
======================================================================== The below is the output of my code:
Selected terminal Connected to card. 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 --- command to open session
ResponseAPDU: 2 bytes, SW=9000 (Nr:0 SW:36864 SW1:144 SW2:0)Bytes received: {-112 0 } (90 00 )Data received: {} ()
Received data.
command ::: 00 a4 04 00 01 11 ---command to select header id : 11
ResponseAPDU: 25 bytes, SW=9000 (Nr:23 SW:36864 SW1:144 SW2:0)Bytes received: {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 90 00 )Data received: {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 )
Received data.
command ::: 00 b0 00 00 00 00 ff --- command to read
ResponseAPDU: 257 bytes, SW=9000 (Nr:255 SW:36864 SW1:144 SW2:0)
06 5e is the max data to receive and 01 46 is the available data. i already read 255 bytes i just need to read remaining 44 bytes. what would be the next offset to retrieve the remaining bytes.