Smart cards: A primer

Develop on the Java platform of the future

1 2 3 Page 2
Page 2 of 3
  • Command -- encapsulate command APDU

  • Response -- encapsulate response APDU

  • ISOCardReader -- specify an interface. Each device has to implement this interface

  • ISOCommand -- construct an ISOCommand and execute the command through the ISOCardReader interface

Communicating with smart cards

Sun has developed the Java Electronic Commerce Framework (JECF), an extension to the core Java platform that allows developers to easily and rapidly develop electronic commerce applications. JECF provides several classes that support communication with smart cards very easily. (See the Resources section for information on the JECF.)

The card we are working with in this article has one command for reading data and another command for writing data. This card is referred to as a GFM card and is produced by GemPlus. You should be able to use other cards as long as they are ISO 7816-compliant and you have the information on what their APDU commands are. Of course you will also have to do a little programing. The GFM card has memory organized in blocks of 64 bits or 8 bytes. You must carry out reads and writes using modulo 8 arithmetic. In other words, you cannot write 1K directly as one long contiguous write. The Java code we supply here does this for you. Some of the newer cards support larger read/write sizes. So, to write the string "0123456789," you would need to issue two commands with proper indexing of the address. (Yes, smart cards can be very difficult to program.) As memory cards and processor cards merge, many of these restrictions are disappearing.

In order to read the above string, you would then need to issue the "read" command.

The two commands we are going to use are formatted below in terms of an APDU. In our case, we use the following Java methods to read and write the card. The values in the table below demonstrate how to construct an APDU. The structure of the APDU is defined in the GFM programmer's manual.

Location of dataUpperLower
256 0X00 0X00
1023 0X00 0X00
3093 0X00 0X00

"Upper" and "lower" are the high- and low-order bytes of the address. Some examples may help clarify this concept. The table provides the upper and lower values for storing data at the specified addresses. The two methods we have been discussing for communication with a GPM896 smart card are:

ISOCommand(0, 0xD0, 0, upper, lower, 8); // Write 8 bytes to the address
ISOCommand(0, 0xB0, 0, upper, lower, 8); // Read 8 bytes from the address

Communicating with a smart card from a browser

The existence of these three native interfaces indicates the lack of understanding of major corporations of developers' need to have simple APIs that they can remember when they are in a Java environment. If all vendors supported JNI, then at least the interface would remain constant and you would not have to spend hours getting the interface bindings to work. It is true that you would still have to write a small amount of "native code," but there is value in having a consistent interface. I have tried all three APIs above and found JNI to be more consistent than the rest, as well as the easiest to use and implement. The integration with HotJava is the best; with HotJava you can sign the classes that talk to a serial port and use them securely with less hassle than with the other two browsers. Sun has recently announced a new initiative to help browser companies implement new versions of the JDK/JVM.

The precceding discussion revolved around how to communicate with a hardware device that does not have JDK support. In the next few articles we will stop concentrating on the "native interfaces" and use an industry standard API for communicating with smart cards. The standard I am choosing for communication is OpenCard with a PC/SC bridge. I will write my appliations to OpenCard not PC/SC. Why?

As a developer you have many choices. Although generally this is a good thing, it also can lead to increased cost and non-uniform functionality when the choices are APIs that do no span all the platforms you need. So, for example, you could decide to write your smart card applications using PC/SC, which provides support in the Win32 world. This is a bad idea because if yours is a consumer application and it is brought up on WebTV, the screen will flash with the message: "Wait for Pentium version of WebTV." Smart cards are used in markets other than Win32 desktops or CE units. So, what should you do? Write to OpenCard and distance yourself from the lack of consistent JNI bindings in Internet Explorer. In fact, I think it is a wise move to abstract all APIs that only function on one platform.

And now, the real-world application!

It's time now to lay out the scene for a more significant smart card application. In the future, when we pay a visit to the doctor and he or she suggests we take a particular medication, we might be players in the following scenario:

  • The doctor asks you for your prescription card.

  • The card is inserted into the reader, and the doctor looks at your prescription history. (For those of us with complex medical/medication histories, an expert system may be necessary.)

  • The doctor notices that another doctor currently has you on a medication that may react with the drug he or she was thinking of prescribing. So the current doctor chooses a different drug and enters the new prescription on your prescription smart card. (Ideally, at this point, the card could transmit the order to the pharmacy.)

  • You take your card to the pharmacy and insert it into the pharmacy's reader.

  • The pharmacist looks at your prescription history and gets the new prescription.

  • Suppose pharmacies have better data on drugs than doctors, and this particular pharmacist thinks the doctor should reconsider the prescribed drug. The pharmacist calls the doctor, whose phone number is included on the prescription smart card. After a brief discussion, the two decide on an alternate medication and update the card.

  • The pharmacist fills your prescription, takes the provider plan information off the card, and communicates with the plan provider using an encrypted protocol.

  • The medical provider verifies that you are actually a plan member, checks that the prescription comes from an authorized doctor, and takes the opportunity to update some data on your card.

  • The pharmacist asks you for five dollars.

Sounds like a safer system to me than the (primarily) paper-and-pen system in which humans are the link between disparate computer systems. In fact, in Germany, medical smart cards are already in use.

The advantages of the prescription smart card

So what value do smart cards add to traditional prescription plan "cards"? They offer:

  • Access to card data when you change stores, travel, or deal with new agencies.

  • Instant access to medical history and medication history for ambulance or ER personnel.

  • Itemized records showing what you have been taking -- including when, where, and how much.

  • Data upload/download to approved recipients.

In order to provide support for the above process, we need to develop an application that lets us read and write records to the card in a secure manner. The application above simply gives the user the ability to enter data onto the card. For example, your doctor can add your prescription to the card.

Developing the application

In this section you get the code you need to write data to a smart card and read it back. The first action in the program that is trying to read or write data to a memory card is to get a reference to a device that supports a smart card. Once we have the device, we need to write or read the desired string. This is achieved by calling on the methods supplied in CardStrings.java. The prototype classes provided facilitate the programming of smart cards. We've also added a Beans-style event handler to inform us of smart card events such as the insertion of a card. (Thanks to Dan Guinan, senior developer on the JECF, for this last tip.)

Consider the following code fragment from RWString.java:

import java.commerce.smartcards.*; Packages form JECF to support smart cards import java.commerce.gemplus.*; import java.commerce.DeviceManager.*; import java.awt.event.*; /** * Read and write Gemplus Memory cards. The following cards * are supported: * GFM 4k */ public class RWString {

public static void main( String args[]) { WriteString ws = new WriteString(args); }

}

class WriteString implements ActionListener {

ISOCardReader isoReader = null; int portNumber; String deviceName;

public WriteString(String args[]) {

//////////////////////////////////// // Process the arguments //////////////////////////////////// for(int i = 0; i < args.length; i++) { if ( args[i].equals("-port") ){ portNumber = 0; } else if ( args[i].equals("-device") ) { deviceName = new String ( args[++i] ); } else if ( args[i].equals("-help") ) { System.out.println("Usage: string -port # -device COM1 or /dev/ttya" ); System.exit(0); } }

SmartCardDetector scDetector = new SmartCardDetector(1000); scDetector.addActionListener(this); scDetector.startDetection(); } public void actionPerformed(ActionEvent actionEvent) { System.out.println("Action Performed: " + actionEvent ); try { // Open the requested port number SmartCardReader scr = new SmartCardReader(); isoReader = scr.getDefault(); isoReader.beginCardSession(GemplusSerialReader.GFM); CardStrings.writeGFMString("01234567" , isoReader ); System.out.println(CardStrings.readGFMString(isoReader ) ); isoReader.endCardSession(); } catch(Exception e) { System.out.println( "Exception " + e); e.printStackTrace(); } finally { try { isoReader.endCardSession(); } catch(Exception eFinally) { System.out.println("Could not power Down card perform manual reset"); } } } }

The class CardStrings provides some utility methods to read and write strings to the card. The strings are stored on the card with a length field of two bytes, followed by six empty bytes, followed by the string data.

As a challenge for those of you who actually get some cards and start programming them, you should be able to modify the methods in Cardstrings to read and write Java objects. This is a more flexible approach than just writing strings. If you write Java objects you can save data without worrying about its format. I wanted to start with something simple that everyone could relate to -- namely, storing some string data on a card.

The following application is a complete example for reading and writing data to a GemPlus GFM card using a GCR400 serial reader. With a little bit of work other readers can be supported. Don't bother doing the work for supporting other readers: Next month we'll be providing an example of how to do this with OpenCard, which is quickly becoming the standard in this area.

1 2 3 Page 2
Page 2 of 3