Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop

Java Smart Card Mini Calculator

4.31/5 (6 votes)
6 Aug 2018CPOL6 min read 42.8K   2.8K  
Communication demonstration between java card and host application

Introduction

This article is about writing Java Smart card based applications. This tutorial will help beginners to understand the concepts and communication between a Java Smart Card and a host application. I have seen beginners of Java Smart Card technology ask simple questions, so I decided to provide them with a complete example to get them started. 

In this article/tutorial I will explain a sample application, a Calculator which will perform four basic operations of calculations, i.e,, + ,-, * and /.

Image 1

Background

In order to understand this tutorial you must know J2SE and have should have basic understanding of (Java) Smart Cards. To get to what java card is please visit the Oracle official site here.

Moreover you might need to have the basics understanding of following standards:

  • ISO 7816-3
  • ISO 7816-4
  • Global Platform 2.1/2.2  

Assumptions 

I am assuming that you have smart card and a smart card reader and you are able to load and install the .cap file provided with this tutorial/article.

Tools Used

  • Netbeans,
  • Java smart card
  • Dell Keyboard reader

Definitions  

What is Smart Card Applet?  

An application which resides on the smart card is called Smart Card Applet. It is written on the computer and then been install on the smart card. 

What is Host Applications?

It is the application which resides on the computer or and interacts with the smart card via APDUs. This application can be written in any programming language.

What is an APDU ?

APDU Stands for Application Programming Data Unit. It is the communication medium between the applet and the host application. All the communication are done between the host application and applet via APDUs. 

APDU is of two types one is command APDU which is send by the Host Application towards the applet and the second is response APDU wich is send by the  as a response of the command APDU back to Host Application.

What is APDU Structure ?

An APDU consists of following fields: 

  • CLA: it is the class of APDU 
  • INS: Instruction what host application wants to do 
  • P1 & P2: Switching parameters  
  • LC: Length of the data
  • Data: Actual data being sent to card
  • LE: Length of data expecting from card

The sequence of above fields should be:

CLA INS P1 P2 LC  Data  LE.

Using the code

Java card application is a sort of Client Server application in which smart card always remains idle and respond to the commands that. Host application sends to it. There is always a response APDU of a command APDU.

In any Smart card applications we need to detect the reader(s) attached with the computer and then have to make connection with that reader and will connect with the card inside that reader.

In the Calculator application I am using a combo-box to display all the available readers and a Button called’ Refresh’ which when clicked populates the combo-box with the attached terminals/readers. After then you have to choose a terminal and click on the ‘Connect’ button to make connection with the smart card. 

I am using SmartCardIO API which comes officially with the JDK 1.6+ that means you don't need to download it, just import it and use it. In calculator application following classes of SmartCardIO are used:

 

Java
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;

To start communication with the card we need to get the reader/terminal first. To do so Java has provided a class TerminalFactory and this class is used to get all the terminals attached with the computer.

Java
public List<CardTerminal> getTerminals() throws Exception{
    factory = TerminalFactory.getDefault();
    terminals = factory.terminals().list();

    return terminals;
}

Above function returns a List of readers that we can display in the combo-box.

After selecting a terminal from the combo-box the user have to click on the Connect button. If there is a card present and and its ATR is working fine then a text Connected will be displayed on the right-bottom side of the frame else corresponding error message will be displayed.

Image 2

Image 3

 

In order to connect with the smart card, we are using Connect() function of the CardTerminal class. To make connection via T=0 you will need to use Connect ("T=0") and for T=1 you have to use Connect("T=1"). But if you are not sure you can use * and the SmartCardIO will detect the communication protocol automatically.

Following method is performing the connect operation:

Java
protected void connectToCard(CardTerminal terninalSource) throws CardException {
    terminal = terninalSource;
    card = terminal.connect("*");
}

After successful connection with the card you need to input digits in the input files and press the calculation operation buttons. 

I am going to explain the (+) operation here the rest of all are the same.

Java
private void add_buttonActionPerformed(java.awt.event.ActionEvent evt) {                                           
        
    String command = "00A404000E63616C63756C61746F722E61707000";
    byte[] apdu = JavaSmartcard.hexStringToByteArray(command);
    if (!selectApplet(apdu))
    {
        return;
    }
    
    byte[] data_LC;
    try 
    {
        data_LC = getLCData(this.digit1_TextField.getText(), this.digit2_TextField.getText());
    }
    catch (Exception ex) 
    {
       JOptionPane.showMessageDialog(this, "Only digits are allowed to input in the fields\n"+
         ex.getMessage(), "Type Error", JOptionPane.ERROR_MESSAGE);
       return;
    }
    
    command = "A000000002"; 
    
    String LC_Hex = JavaSmartcard.byteArrayToHexString(data_LC);     
         
    command = command.concat(LC_Hex);                
    
    apdu = JavaSmartcard.hexStringToByteArray(command);
    System.out.println(""+ JavaSmartcard.htos(apdu));
    try
    {
        javaCard.sendApdu(apdu);
        byte[] data = javaCard.getData();
        
        this.status_Label.setText(""+Integer.toHexString(javaCard.getStatusWords()).toUpperCase());
        this.result_Label.setText(new BigInteger(data)+"");
    } 
    catch (CardException | IllegalArgumentException ex) 
    {
        JOptionPane.showMessageDialog(this, "Error while tried to send command APDU\n"+
          ex.getMessage()+"", "APDU sending fail", JOptionPane.ERROR_MESSAGE);
    }
}

In the above function I am first selection the applet and on the successful selection I am preparing the APDU which will instruct the applet what to do and what data it has. 

Java
command = "00A404000E63616C63756C61746F722E61707000"; 

Above is the select applet APDU as we need to select our calculator applet first in order to do calculation otherwise the default applet might not accept your subsequent command APDUs.

Java
byte[] apdu = JavaSmartcard.hexStringToByteArray(command); 

After preparing the APDU I am gonna convert it into the byte array to transmit to the card.  hexStringToByteArray is a utility function used to convert a hex string into byte array.

Java
command = "A000000002"; 

Above APDU  A000000002 is the APDU which will tell the applet that you have to add given two digits. I am gonna to explain its fields here below:

  • CLA: AO
  • INS:  00
  • P1 & P2:  00, 00
  • LC : 02 

Data part is calculated as below:

Java
private byte[] getLCData(String byte1Str, String byte2Str) throws Exception
{
    byte[] data_LC = new byte[2];
    byte byte1 =  Byte.parseByte(byte1Str );
    byte byte2 =  Byte.parseByte(byte2Str);
    data_LC[0] = byte1;
    data_LC[1] = byte2;
  
    return data_LC;
}

I am converting the inputs of both the TextFields into the byte and then copying that bytes into a byte array to transmit to the card.

The final APDU will looks like below. Let user enters 5 and 5 and input.

HTML
A0 00 00 00 02 05 05

When smart card gets that APDU it will interprets it and find the INS field to know what the Host Application want to do and then it will gets the data (digits) from the Data part and will add and returns it to the Host Application in the form of response APDU.

When the response APDU received, we can determine the STATUS WORD to get to know what happened during the calculation. If card returns a STATUS WORD of 0x9000 that will means that everything was went fine and else there might be error or do perform further actions to get the actual response APDU.

Java
public int getStatusWords() {
    return rAPDU.getSW();
}

The above function is used to get the STATUS WROD return by the card and by using the below function I am getting the Data part.

Java
public byte[] getData() {
    if (rAPDU!=null) {
        return rAPDU.getData();
    }
    else {
        return null;
    }
}

Rest of the code is simple and self-explanatory. I will try to add another tutorial on writing the calculator applet which I am attaching with this article. 

 

Further readings can be done on blog: https://gosiebel.blogspot.com/

Points of Interest 

In this example no special or third party dll, library or API is being used. Everything is done by using the Java provided SDK.

Limitations

As smart cards are limited resource and computations enabled devices so this calculator worked with the rang of 1-127 inclusive. The reason is that I am converting the input into byte and a byte can contains 127 signed values.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)