本文改编自:http://www.dreamingfish123.info/?p=580,旨在对原文进行扩展,对JCDK v3.0.0.5的情况进行说明。
Java Card是基于硬件与应用的要求所开发的技术,目的是使得Java技术能够再如同smart card芯片般大小的有限资源下执行,是能运行Java程序的智能卡。Java Card技术提供了一种开放式开发构架,现在的智能卡开发者可以开发出在多种智能卡上应用的程序,不同的应用程序可以在同一个卡片上运行。
从一个 applet 的编写、编译、转换、部署、使用的过程看,会是这样的与脚本相关的过程:
目前Oracle已经提供了所有开发Java Card Applet所需要的tools、libraries和一系列的APIs,最多使用的是2.2.1和2.2.2版本。
Note: 目前还不需要用到JCDK 3.x,因为还没有实体java卡支持其开发,而在没有可以实时部署和测试的环境的情况下,去学习这个版本试没有意义的。
JCDK中包含Converter、APDUTool、ScriptGen等重要的工具,还提供两个Java智能卡运行环境的仿真工具Cref和JCWDE,通过这两个工具,无需读/写器和智能卡卡片,开发人员可以在PC软件平台上模拟Java智能卡的运行,进行Applet的调试运行。
几个比较重要的functions:
public static void install(byte[] bArray, short bOffset, byte bLength){}
public void process(APDU apdu){}
protected final void register(){}
//or protected final void register(byte[] bArray, short bOffset, byte bLength){} throws SystemException public boolean select(){}
EclipseJCDE提供了一组编译时验证,当Java Card应用程序在安装或运行在模拟器上时验证Java卡项目的一致性,避免运行时错误。
EclipseJCDE提供以下的验证:
Applet实现功能:将所有发送给此Applet的命令原封不动的返回给卡外应用。
该sample以CREF作为模拟器,用两种方法实现整个开发流程:Eclipse+JCDE 和 CMD
例如javacard_env.bat
1
2
3
4
5
|
@
echo
off
set
JC_HOME=C:\java_card_kit-2_2_2-windows\java_card_kit-2_2_2
set
JAVA_HOME=C:\jdk1.5.0_22
set
PATH=.;%JC_HOME%\bin;%JAVA_HOME%\bin;%PATH%
set
CLASSPATH=%JC_HOME%\lib\api.jar;%CLASSPATH%
|
Note:jdk的路径最好不要有空格,默认是装到”program files”目录下,这就有空格,会导致后面一些命令出错。
编译sample applet中的java源代码:
1
|
javac -g HelloWorld.java
|
转换class文件,生成 .cap, .exp, .jca文件,其中 .cap 文件是实际加载安装到java card中的文件。
1
2
3
4
5
6
|
-out EXP JCA CAP
-exportpath E:\HUI\java_card\java_card_kit-2_2_2-windows\java_card_kit-2_2_2\api_export_files
-classdir E:\HUI\java_card\HelloWorld\bin
-applet 0xa0:0x0:0x0:0x0:0x62:0x3:0x1:0xc:0x1:0x1 com.sun.javacard.samples.HelloWorld.HelloWorld
com.sun.javacard.samples.HelloWorld
0xa0:0x0:0x0:0x0:0x62:0x3:0x1:0xc:0x1 1.0
|
再在CMD中输入命令:
1
|
converter -config E:\HUI\java_card\HelloWorld\src\HelloWorld.opt
|
Note:
用scriptgen工具生成apdutool所需要的脚本文件*.scr,脚本文件中是一序列的APDU,可以被送进java card中以安装特定的CAP文件。
1
|
scriptgen -o E:\HUI\java_card\HelloWorld\bin\com\sun\javacard\samples\HelloWorld\javacard\HelloWorld.scr E:\HUI\java_card\HelloWorld\bin\com\sun\javacard\samples\HelloWorld\javacard\HelloWorld.cap
|
可以得到HelloWorld.scr,但是scriptgen所产生的.scr还需要加上头尾的.scr才是完整的.scr(for download to CREF),所以需要在该脚本文件头尾加上:
1
2
3
4
5
6
7
8
9
10
11
|
//
Power up
powerup;
//
Select the installer applet
0x00 0xA4 0x04 0x00 0x09 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x08 0x01 0x7F;
//
the
//
body
//
part
//
of
//
HelloWorld.src
//
Power down
powerdown;
|
其中cap-download.script = 加上头尾后的HelloWorld.scr
Note:
script file的内容可分为4个部分:
其中scriptgen所产生的.scr文件只有第一部分的download .CAP部分,其余部分需要自行加入。
*第一部分必须在文件头自行加上:
1
2
3
4
|
powerup;
//
Select the installer applet
0x00 0xA4 0x04 0x00 0x09 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x08 0x01 0x7F;
//
90 00 = SW_NO_ERROR
|
目的是让Java卡Power up之后,并选择了installer applet,再由installer applet将所需要download到卡上的 .cap 文件进行download.
*第二部分必须加上:
1
2
3
4
5
6
|
//
create Test applet(AID需自行填入)
echo
"Create Test Applet:"
;
0x80 0xB8 0x00 0x00 0x0c 0x0a 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0xc 0x01 0x01 0x00 0x7F;
//
Select Applet AID(AID需与create applet 相同)
echo
"Select Test Applet:"
;
0x00 0xa4 0x04 0x00 11 0xA0 0x00 0x00 0x02 0x83 0x00 0x00 0x08 0x12 0x00 0x03 0x7F;
|
其中create applet的APDU格式为:
| 0x8x, 0xb8, 0×00, 0×00 | Lc field | AID length field | AID field | parameter length field | [parameters] | Le field |
select applet的APDU格式为:
| 0x0x, 0xa4, 0×04, 0×00 | Lc field | Installer AID | Le field |
*第三部分则根据applet之所需执行的apdu command由user自行定义并加入
*第四部分则必须在文档最后加入:
1
|
powerdown;
|
利用 cap-download.script / HelloWorld.scr 脚本,将 applet 部署到卡(虚拟机的 eeprom文件)中
1
|
cref -o HelloWorldImage
|
再打开一个命令提示符窗口,执行:
1
|
apdutool E:\HUI\java_card\HelloWorld\bin\com\sun\javacard\samples\HelloWorld\javacard\HelloWorld.scr
|
运行结果:
Java Card 2.2.2 APDU Tool, Version 1.3
Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Opening connection to localhost on port 9025.Connected.
Received ATR = 0x3b 0xf0 0×11 0×00 0xff 0×01
CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 09, a0, 00, 00, 00, 62, 03, 01, 08, 01, Le: 00, SW1: 90, SW2: 00
CLA: 80, INS: b0, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 90, SW2: 00
***此处省略部分结果
CLA: 80, INS: b4, P1: 09, P2: 00, Lc: 16, 09, 00, 13, 00, 03, 0e, 26, 2b, 00, 0c, 05, 0c, 06, 04, 08, 05, 11, 0c, 07, 09, 06, 09, Le: 00, SW1: 90, SW2: 00
CLA: 80, INS: bc, P1: 09, P2: 00, Lc: 00, Le: 00, SW1: 90, SW2: 00
CLA: 80, INS: ba, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 90, SW2: 00
由运行结果可见SW1=90,SW2=00,意味着在Cref中已经正确安装了Java Card Applet。
在运行Cref命令窗口的当前工作目录中会发现生成了一个新文件HelloWorldImage。这个文件就是通过APDUTool下载到Cref环境中的内存镜像文件。
1
2
|
//
CAP end
0x80 0xBA 0x00 0x00 0x00 0x7F;
|
后面添加一段APDU命令:
1
2
3
4
5
6
|
// Create HelloWorld
0x80 0xB8 0x00 0x00 0x0c 0x0a 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0xc 0x01 0x01 0x00 0x7F;
// Select HelloWorld
0x00 0xA4 0x04 0x00 10 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0xc 0x01 0x01 0x7F;
// Sending the testing APDU command, and the received data should be echo from the whole APDU command
0x00 0xFF 0x00 0x00 0x0b 'H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd' 0x7F;
|
从eclipse的Console中可以看到运行结果:
//前面部分和APDUTool-Downloading the CAP file中的运行结果相同。
CLA: 80, INS: b8, P1: 00, P2: 00, Lc: 0c, 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, 00, Le: 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, SW1: 90, SW2: 00
CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, Le: 0f, 00, a4,
04, 00, 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, SW1: 90, SW2: 00
CLA: 00, INS: ff, P1: 00, P2: 00, Lc: 0b, 48, 65, 6c, 6c, 6f, 20, 57, 6f, 72, 6c, 64, Le: 10, 00,
ff, 00, 00, 0b, 48, 65, 6c, 6c, 6f, 20, 57, 6f, 72, 6c, 64, SW1: 90, SW2: 00

可以看到SW1=90且SW2=00,同时最后测试APDU的datac(即Lc后部分)为“Hello World”字符串,Applet相应的字串datae(即Le后部分)为整个输入的APDU command。
所以测试成功。
1
|
cref -i HelloWorldImage
|
这个命令使得当前窗口处于阻塞状态,直到有APDU命令请求到来。在 E:\HUI\java_card\HelloWorld\bin\com\sun\jav
acard\samples\HelloWorld\javacard\ 目录下建立 test_HelloWorld.scr:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// Power up
powerup;
// Create the applet
0x80 0xB8 0x00 0x00 0x0b 0x0a 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x0c 0x01 0x01 0x7F;
// Select the applet
0x00 0xa4 0x04 0x00 0x0a 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x0c 0x01 0x01 0x7F;
// User APDU command 1
0x80 0x50 0x00 0x00 0x0b 0x01 0x00 0x00 0x00 0x02 0x01 0x02 0x03 0x04 0x05 0x06 0x7F;
// User APDU command 2
0x80 0x52 0x00 0x00 0x0b 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0xa0 0x83 0xd0 0x43 0x7F;
// User APDU command 3
0x80 0x50 0x01 0x00 0x0b 0x03 0x00 0x00 0x00 0x05 0x01 0x02 0x03 0x04 0x05 0x06 0x7F;
// User APDU command 4
0x80 0x54 0x00 0x00 0x0F 0x01 0x02 0x03 0x04 0x04 0x03 0x02 0x01 0x03 0x02 0x01 0x01 0x02 0x03 0x04 0x7F;
// Power down
powerdown;
|
在APDUTool命令窗口,执行APDUTool命令:
1
|
apdutool E:\HUI\java_card\HelloWorld\bin\com\sun\javacard\samples\HelloWorld\javacard\test_HelloWorld.scr
|
将测试脚本文件作为参数,执行结果直接输出到命令窗口中。此时Cref命令窗口中的执行结果:
Java Card 2.2.2 APDU Tool, Version 1.3
Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
Opening connection to localhost on port 9025.
Connected.
Received ATR = 0x3b 0xf0 0×11 0×00 0xff 0×01
CLA: 80, INS: b8, P1: 00, P2: 00, Lc: 0b, 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, Le: 0a, a0,
00, 00, 00, 62, 03, 01, 0c, 01, 01, SW1: 90, SW2: 00
CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, Le: 0f, 00, a4,
04, 00, 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, SW1: 90, SW2: 00
CLA: 80, INS: 50, P1: 00, P2: 00, Lc: 0b, 01, 00, 00, 00, 02, 01, 02, 03, 04, 05, 06, Le: 10, 80,
50, 00, 00, 0b, 01, 00, 00, 00, 02, 01, 02, 03, 04, 05, 06, SW1: 90, SW2: 00
CLA: 80, INS: 52, P1: 00, P2: 00, Lc: 0b, 01, 02, 03, 04, 05, 06, 07, a0, 83, d0, 43, Le: 10, 80,
52, 00, 00, 0b, 01, 02, 03, 04, 05, 06, 07, a0, 83, d0, 43, SW1: 90, SW2: 00
CLA: 80, INS: 50, P1: 01, P2: 00, Lc: 0b, 03, 00, 00, 00, 05, 01, 02, 03, 04, 05, 06, Le: 10, 80,
50, 01, 00, 0b, 03, 00, 00, 00, 05, 01, 02, 03, 04, 05, 06, SW1: 90, SW2: 00
CLA: 80, INS: 54, P1: 00, P2: 00, Lc: 0f, 01, 02, 03, 04, 04, 03, 02, 01, 03, 02, 01, 01, 02, 03,
04, Le: 14, 80, 54, 00, 00, 0f, 01, 02, 03, 04, 04, 03, 02, 01, 03, 02, 01, 01, 02, 03, 04, SW1:
90, SW2: 00
从测试结果可以看到:SW1=90,SW2=00,说明测试没有问题。
Note: