How to read file from smart card using java
Asked Answered
A

2

6

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.

Aftercare answered 18/4, 2016 at 12:3 Comment(7)
What have you done? What did you expect to happen? What happened instead?Cyrillus
@Henry. Done : connect smart to system. Expect : want to communication with smart card. Happened : Throe error, p1 and p2 parameter are wrong. When i pass command to smart card. I have no more knowledge about apdu command.Aftercare
I don't think you are using a java card library. You are probably using javax.smarcardio. This is a JAVA library. For further information about how to read your card, read the ISO7816-4 and thee smartcard vendor documentationCarline
@PaulBastian yes i am used javax.smarcardio. And not getting proper guidance for APDU commands.Aftercare
@PaulBastian, sorry for asking can you please share link for same. I am reading cardwerk.com/smartcards/…Aftercare
@KrunalIndrodiya just click on Part 4 on the pageCyrillus
@Cyrillus Thanks man.Aftercare
A
4

First of all:

"Not" all Java cards have MF, DF and EF inside! 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.

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).

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.

2-You can use Javax.smartcardio library for writing your Java program to communicate with smart cards:

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:

#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.

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.

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. What you need to do to receive this response (i.e. 11 22 33 44 55) is as below:

  1. Send a SELECT APDU command with you applet's AID in its data field.
  2. Sending 00 00 00 00 00 to your applet.
  3. Your applet response to the above command with expected answer.

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.

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).

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.

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

Anuran answered 18/4, 2016 at 12:24 Comment(7)
Is there a command to query what is the currently selected applet?Empery
@typelogic No, there isn't unfortunately.Anuran
Thanks @EbrahimGhasemi - really nicely explained 👍 I'm just wondering is there a way to "scan" the card and check what the applets are in there? Eg. I know I expect to see 2 applets installed. I have the AID of the first one, but I'm missing AID for the second one so I'm not able to select it and proceed with the commands...Meleager
@Meleager You are welcome. Well, if you have the mutual authentication keys of the Card Manager (AKA Security Domain), then you can ask a list of AIDs of installed applets and packages from the Card Manager. To do so, you can use gp -l in GlobalPlatformPro tool.Anuran
@Meleager But if you don't have the Card Manager's mutual authentication keys (AKA GlobalPlatform Keys), you need to do a brute-force search (send a lot of SELECT APDU commands with all possible AIDs). But unless your card does support "Partial APDU Selection" feature, brute-force would not be feasible in practice (we have 2^40 + 2^48 + 2^56 + ... + 2^128 different possible AID!). If your card support Partial APDU Selection, then you can find all the AIDs in hour or hours. By Partial APDU selection Card Manger selects the first applet that matches the substring of the AID in thr APDU command.Anuran
@Meleager So you can send 00 A4 04 00 01 00 to card and if there is any applet in the card which its AID starts with 00, you receive a 9000 status words. then you go for the second byte of the AID by sending APDU commands from 00 A4 04 00 02 00 00 to 00 A4 04 00 02 00 FF. And so on, until the last byte of applet's AID. It's a little tricky, so if my explanation is vague, don't hesitate to ask more questions. You can also post a new SO question and I will provide an answer there.Anuran
Thanks a lot for your feedback @EbrahimGhasemi! I got your point - this is basically a kind of manual scanning aiming to hit the AID. I'll definitely give it a chance, just wanted to check first is there already some existing solution available what could automate this for me :D. Will let you know how it goes!Meleager
C
1

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

You can see link1 and Link2 for more about smart card file structure.

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).

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.

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.

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.

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.

Concordat answered 22/4, 2016 at 9:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.