Just tried to test a simple Java Card STK applet on (U)SIM cards, it was easy to prepare the applet, but it is tricky to convert to cap file and download to the real cards.
The source code is quite simple, just setup menu itme "Hello, STK", if click, then it will display "Welcome toorCamp 2012", as below,
package com.test.helloworld;
//import javacard.framework.*;
//import javacardx.annotations.*;
//import static com.test.helloworld.helloworldStrings.*;
import javacard.framework.APDU;
import javacard.framework.Applet;
//import javacard.framework.ISOException;
//import sim.toolkit.EnvelopeHandler;
import sim.toolkit.*;
/**
* Applet class
*
* @author <user>
*/
//@StringPool(value = {
// @StringDef(name = "Package", value = "com.test.helloworld"),
// @StringDef(name = "AppletName", value = "helloworld")},
//Insert your strings here
//name = "helloworldStrings")
public class helloworld extends Applet implements ToolkitInterface, ToolkitConstants {
// DON'T DECLARE USELESS INSTANCE VARIABLES! They get saved to the EEPROM,
// which has a limited number of write cycles.
private byte helloMenuItem;
//private static ToolkitRegistry reg;
static byte[] welcomeMsg = new byte[] { 'W', 'e', 'l', 'c', 'o', 'm', 'e', ' ',
't', 'o', ' ', 'T', 'o', 'o', 'r', 'C',
'a', 'm', 'p', ' ', '2', '0', '1', '2' };
static byte[] menuItemText = new byte[] { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'S', 'T', 'K'};
/**
* Installs this applet.
*
* @param bArray
* the array containing installation parameters
* @param bOffset
* the starting offset in bArray
* @param bLength
* the length in bytes of the parameter data in bArray
*/
public static void install(byte[] bArray, short bOffset, byte bLength) {
//new helloworld();
helloworld applet = new helloworld();
applet.register();
}
/**
* Only this class's install method should create the applet object.
*/
protected helloworld() {
//register();
// This is the interface to the STK applet registry (which is separate
// from the JavaCard applet registry!)
ToolkitRegistry reg = ToolkitRegistry.getEntry();
//reg = ToolkitRegistrySystem.getEntry();
// Define the applet Menu Entry
helloMenuItem = reg.initMenuEntry(menuItemText, (short)0, (short)menuItemText.length,
PRO_CMD_SELECT_ITEM, false, (byte)0, (short)0);
}
// This processes STK events.
public void processToolkit(byte event) throws ToolkitException {
EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();
//EnvelopeHandler envHdlr = EnvelopeHandlerSystem.getTheHandler();
if (event == EVENT_MENU_SELECTION) {
byte selectedItemId = envHdlr.getItemIdentifier();
if (selectedItemId == helloMenuItem) {
showHello();
}
}
}
private void showHello() {
ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
//ProactiveHandler proHdlr = ProactiveHandlerSystem.getTheHandler();
//proHdlr.initDisplayText((byte)0, DCS_8_BIT_DATA, welcomeMsg, (short)0,
proHdlr.initDisplayText((byte)0, (byte)0x04, welcomeMsg, (short)0,
(short)(welcomeMsg.length));
proHdlr.send();
return;
}
/**
* Processes an incoming APDU.
*
* @see APDU
* @param apdu
* the incoming APDU
*/
//@Override
public void process(APDU apdu) {
//Insert your code here
// ignore the applet select command dispached to the process
if (selectingApplet())
return;
}
}
It is important to keep the same version JCDK and JDK version when compiling and converting from class file to cap file, and it is not the case the latest version will be working better, instead keep in the old version will be more safe and less problem.
I downloaded JDK 1.8, JDK1.4.2, JCDK 3.0.5, finally I used JDK1.4.2 and JCDK 2.2.1, actually the JDK version doesn't matter, the JDK compliant level matters, and I have tried different combination to see if they are working properly together, found it is not related to Eclipse version, the JDK (compliant level) and JCDK version counts to the results, refer to this Link for some idea...
Configure the Eclipse IDE, configure the library usage, add JDK 1.4.2 or JDK 1.8, JCDK api.jar and JCDK sim.jar, as below picture shows,
Configure Java compiler compliance level as 1.3 (or some other level, you will need to try), as below picture shows, you can find detail of different compliance level result in following description, it will return different errors when doing the cap file converting, it looks like the JDK (compliant level) and JCDK version not match caused errors.
When doing the cap file converting, the JAVA_HOME should be at a higher version (I set mine as JDK 1.8, and remember to set the export library), as below picture shows, otherwise it will return below error,
java.lang.UnsupportedClassVersionError: com/sun/javacard/converter/Main (Unsupported major.minor version 50.0)
Setup the package AID information, as below picture shows,
JCDK 3.0.2 work with JDK1.8, result as below (different combination),
Set compiler compliant level as 1.8, when do converting of the cap file, return below error,
error: com.test.helloworld.helloworld: unsupported class file format of version 52.0.
Set compiler compliant level as 1.7, when do converting of the cap file, return below error,
error: com.test.helloworld.helloworld: unsupported class file format of version 51.0.
Set the compiler compliant level as 1.6, the cap file was successfully converted, result as below,
CurDir=E:\ECLIPSE-JEE-MARS\WORKSPACE\HELLOWORLD1\BIN\COM\TEST\HELLOWORLD
Java_Home=C:\PROGRA~1\Java\JDK18~1.0_9
JC_Home=C:\JCDK30~1.2_C
================== Converting ==================
[ INFO: ] Converter [v3.0.2]
[ INFO: ] Copyright (c) 2009 Sun Microsystems, Inc.
All rights reserved.
Use is subject to license terms.
[ INFO: ] conversion completed with 0 errors and 0 warnings.
================== Exp2Text ==================
Exp2Text [v3.0.2]
Copyright (c) 2009 Sun Microsystems, Inc.
All rights reserved.
Use is subject to license terms.
conversion completed with 0 errors and 0 warnings.
JCDK 2.2.1 work with JDK1.8, result as below,
Set compiler compliant level as 1.8, when do converting of the cap file, return below error,
error: com.test.helloworld.helloworld: unsupported class file format of version 52.0.
Set compiler compliant level as 1.7, when do converting of the cap file, return below error,
error: com.test.helloworld.helloworld: unsupported class file format of version 51.0.
Set compiler compliant level as 1.6, when do converting of the cap file, return below error,
error: com.test.helloworld.helloworld: unsupported class file format of version 50.0.
Set compiler compliant level as 1.5, when do converting of the cap file, return below error,
error: com.test.helloworld.helloworld: unsupported class file format of version 49.0.
Set compiler compliant level as 1.4, the cap file was successfully converted, result as below,
CurDir=E:\ECLIPSE-JEE-MARS\WORKSPACE\HELLOWORLD1\BIN\COM\TEST\HELLOWORLD
Java_Home=C:\PROGRA~1\Java\JDK18~1.0_9
JC_Home=C:\JAVA_C~2
================== Converting ==================
Java Card 2.2.1 Class File Converter, Version 1.3
Copyright 2003 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
conversion completed with 0 errors and 0 warnings.
================== Exp2Text ==================
Java Card 2.2.1 Exp to Text, Version 1.3
Copyright 2003 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
conversion completed with 0 errors and 0 warnings.
Download the cap file to real card and install.
If you have the ISD AID and key, you can do the external authentication and then download/install the applet.
I tried the JCManager, not sure how it works, need to put something there in the Install parameters..
encountered "Could not initialize class com.linuxnet.jpcsc.PCSC" error, needs to put the jpcsc.jar to the system32 folder, refer to this Link
Optionally you can also use the "SimAllianceLoader_v2", it will go through OTA, and it requires to know the OTA keys, will share the detail later..
Reference Link:
1, Java Card Platform, Classic Edition 3.0.5
2, Eclipse Java Card Plug-in
3, https://github.com/gelvaos/otp
4, http://gelvaos.blogspot.sg/2012/10/javacard-stk-usage-example-one-time.html
5, Gemalto_JavaCard_DevelGuide.pdf
6, JavaCard Applets
7, Java SE Development Kit 8 Downloads
8, Java SE 1.4 Downloads