什么是智能卡?
智能卡不是新鲜事物。它们在二十年前在欧洲就以记忆卡片的形式推出了,用于保存关键的电话信息,以减少盗打付费电话的可能
智能卡技术是ISO国际标准组织的连接技术委员会1(JTC1)和国际电子委员会(IEC)定义并控制的一种行业标准。1987年推出的ISO/IEC 7816国际标准系列在2003年推出了它的最新的升级版本,定义了智能卡的各个方面,包括物理特征、物理接触界面、电子信号和传输协议、命令、安全体系、应用程序标识符和公用数据元素等。
智能卡是一个包含嵌入集成电路(IC)的塑料卡片,类似于一张信用卡。当用作SIM卡时,这个塑料卡片很小,正好能放入手机中。智能卡设计时就极注重高度安全性,窜改一点点内容都会导致毁坏它包含的信息。
在智能卡使用的某些领域,它们只是仅仅提供受保护的非易失性存储。更高级的智能卡还有微处理器和内存,用于安全的处理和储存,并且可以用于使用公共密钥或者共享密钥算法的安全应用程序。智能卡上的非易失性存储是最宝贵的资源,可用于保存秘钥和数字证书。一些智能卡有单独的加密协处理器,支持象RSA、AEC和(3)DES这样的算法。
智能卡不包含电池,只有在和读卡机连接的时候才被激活。当它被连接时,在执行一个复位序列之后,卡片处于非激活状态,等待接收来自客户端(主机)应用程序的命令请求。
智能卡可以分为可接触和非可接触。可接触智能卡通过读卡器和智能卡的8个触点物理接触来通讯并工作,而非可接触智能卡依靠在小于2英尺的一般距离之内的射频信号通讯。非接触智能卡的射频通信基于类似于用于保存反盗窃和记录清单的射频标识符( RFID)标记的技术。图1描述了可接触和非可接触智能卡:
图 1a .接触式智能卡
图1b.非接触式智能卡
Java Card技术还存在除了智能卡之外的其它的形态,例如智能按钮和USB令牌,这两种如图2所示。这些的功能和智能卡差不多,例如用于验证用户或者传送敏感信息。智能按钮包含一块电池而且是基于可接触模式,而USB令牌则可以直接插入个人计算机的USB端口,而不需要任何可接触或者非可接触读卡器。这两种类型的Java Card具有与智能卡相同的编程能力并且具有防篡改能力。
图 2a . 带有Java功能的智能纽扣
图2b. 带有Java功能的USB 令牌
JavaCard规范
多年以前,Sun微系统公司实现了智能卡和类似的资源约束设备的潜能,并且定义了一组Java技术子集规范来为它们创建应用程序,Java Card小应用程序。支持这些规范的设备称为Java Card平台。在一个Java Card平台上,来自不同的供应商的多个应用程序可以安全地共存。
一个典型的Java Card设备有一个8或16位的运行在3.7MHz的中央处理器,带有1K的RAM和多于16K的非易失性存储器(可编程只读存储器或者闪存)。高性能的智能卡带有单独的处理器和加密芯片,以及用于加密的内存,并且有一些还带有32位的中央处理器。
Java Card技术规范目前是2.2版,由三部分组成:
Ø Java Card虚拟机规范,定义了用于智能卡的Java程序语言的一个子集和虚拟机。
Ø Java Card运行时环境规范,进一步定义了用于基于Java的智能卡的运行期行为。
Ø Java Card应用编程接口规范,定义了用于智能卡应用程序核心框架和扩展Java程序包和类。
Sun还提供了Java Card开发工具箱(JCDK) http://java.sun.com/products/javacard/,包含了Java Card运行期环境和Java Card虚拟机的引用实现,和其它帮助开发Java Card小应用程序的工具。本文的第二部分将详细讲述JCDK。
JavaCard应用程序的元素
完整的Java Card应用程序由一个后端应用程序和系统、一个主机(卡外)应用程序、一个接口设备(读卡器)和卡上小应用程序、用户证书和支持软件组成。所有的这些元素共同组成一个安全的端到端应用程序
一个典型的Java Card应用程序不是孤立的,而是包含卡端、读取端和后端元素。让我们更详细的讲述一下每个元素。
后端应用程序和系统:
后端应用程序提供了支持卡上Java小应用程序的服务。 例如,一个后端应用程序可以提供到安全系统和卡上的证书的连接,提供强大的安全性。在一个电子付款系统中,后端应用程序可以提供到信用卡及其他付款信息的访问。
读取端主应用程序:
主应用程序存在于一个例如个人计算机这样的台式机或者终端、电子付款终端、手机或者一个安全子系统中。
主应用程序处理用户、Java Card小应用程序和供应商的后端应用程序之间的通讯。
传统的读取端应用程序是使用C编写的。近来J2ME技术的广泛普及有望使用Java实现主应用程序;例如,它可以在一台支持MIDP和安全信赖服务应用编程接口(Security and Trust Services API)手机上运行。
智能卡供应商一般不仅提供开发工具箱,而且提供支持读取端应用程序和Java Card小应用程序的应用程序编程接口。例如OpenCard Framework http://www.opencard.org/,就是一个基于Java的应用程序编程接口集,隐藏了来自不同供应商的读取器的一些细节,并且提供了Java Card远程方法调用分布式对象模型和安全信任服务应用编程接口(SATSA),我在本文后面一部分讨论它们。
读取端卡片接受设备:
卡片接受设备(CAD)是处于主应用程序和Java Card设备之间的接口设备。一个CAD为卡片提供电力,以及与之进行电子或者射频通信。一个CAD可能是一个使用串行端口附于台式计算机的读卡器,或者可能被整合到终端内,例如饭店或者加油站内的电子付款终端。接口设备从主应用程序到卡片转送应用程序协议数据单元( Application Protocol Data Unit,简称APDU)命令(在后面讨论),并且从卡片向主应用程序转送响应。一些CAD有用于输入个人识别号码的键盘,有的可能还有显示屏。
卡片端小应用程序和环境:
Java Card平台是一个多应用程序环境。在图4中我们可以看到,卡片上可能存在一个或多个Java Card小应用程序,还有支持软件--卡片的操作系统和Java Card运行时环境(JCRE)一起。JCRE由Java Card虚拟机、Java Card Framework和应用程序编程接口以及一些扩展应用程序编程接口组成。
所有的Java Card小应用程序扩展Applet基本类,并且必须实现install()和process()方法;JCRE在安装小应用程序的时候调用install(),并且在每次有一个进入的用于小应用程序的APDU的时候调用process()。
Java Card小应用程序在被装载的时候实例化,并且在断电的时候保持运行。Java Card小应用程序起一个服务器的作用,并且是无源的。在一张卡片被加电以后,每个小应用程序都保持非运行的状态直到它被选择,在此时可能会做初始化。小应用程序只有在一个APDU被发送给它以后才被激活。一个小应用程序如何激活(被选择)在"一个Java Card小应用程序的生命周期"一节中描述。
与Java Card小应用程序通讯(访问智能卡):
你可以使用两种模型中的任何一种来在一个主应用程序和一个Java Card小应用程序之间通信。第一个模型是基本消息传送模型,第二种是基于Java Card远程方法调用(JCRMI),这是J2SE RMI分布式对象模型的一个子集。此外,SATSA通过一个基于更加抽象的应用编程接口的普通连接框架(Generic Connection Framework,简称GCF)应用编程接口,让你要么使用消息传递要么使用JCRMI来访问智能卡。
消息传递模型
图1中说明的消息传递模型是所有Java Card通信的基础。它的核心就是应用程序协议数据单元(APDU),CAD和Java Card框架之间交换的一个逻辑数据包。JavaCard框架接收任何CAD发送进来的APDU命令并且传送到相应的小应用程序中。小应用程序处理APDU命令,然后返回一个响应APDU。那些APDU遵守国际标准规格ISO/IEC 7816 - 3和7816 – 4
图1使用消息传递模型通讯
读卡器和卡之间的通信通常基于下面两种连接协议的一种,面向字节的T = 0,或者面向数据块的T = 1。还可能会用到被称为T = USB和T = RF的替换协议。JCRE APDU类向应用程序隐藏了一些协议细节,但不是全部,因为T = 0协议相当的复杂。
⒈APDU命令
一个APDU命令的结构由它的第一个字节的值控制,大部分情况下看上去如下所示:
图2、APDU命令
一个APDU命令有一个必须有的头和一个可选的体,包含:
Ø CLA(1字节):这个必要的字段识别指令的一个特定应用程序类。有效的CLA值在ISO 7816 - 4规范中定义:
表格1、ISO 7816 CLA值
CLA 值 |
指令类 |
0x0n, 0x1n |
ISO 7816 - 4卡指令,比如文件存取和安全操作 |
20 to 0x 7F |
保留 |
0x8n or 0x9n |
你可以用作你的特定的应用程序指令的ISO/IEC 7816 - 4格式,根据标准解释' X ' |
0xAn |
特定的应用程序或者供应商的指令 |
B0 to CF |
你可以用作特定应用程序的ISO/IEC 7816 - 4格式 |
D0 to FE |
特定的应用程序或者供应商的指令 |
FF |
保留给协议类型选择 |
理论上,你可以使用所有的CLA值0x80或者更高值来用于特定应用程序指令,但是在许多现在的Java Card实现中,只有黑体显示的是实际认可的。
Ø INS(1字节):这个必需的字段指明CLA字段中标示的指令类中的一个特定指令。ISO 7816 - 4标准指定用于访问卡上的数据的基本指令,当它根据在像标准中定义的卡上的文件系统那样结构化的时候。附加功能已经在这个标准中的其它地方说明,其中一些是安全功能。表2中是一个ISO 7816指令的列表。只有当使用一个相应的CLA字节值时,你才可以根据标准定义你自己的特定应用程序的INS值,。
表格2、当 CLA = 0x时的ISO 7816 - 4 INS值
INS 值 |
命令描述 |
0E |
Erase Binary |
20 |
Verify |
70 |
Manage Channel |
82 |
External Authenticate |
84 |
Get Challenge |
88 |
Internal Authenticate |
A4 |
Select File |
B0 |
Read Binary |
B2 |
Read Record(s) |
C0 |
Get Response |
C2 |
Envelope |
CA |
Get Data |
D0 |
Write Binary |
D2 |
Write Record |
D6 |
Update Binary |
DA |
Put Data |
DC |
Update Record |
E2 |
Append Record |
Ø P1(1字节):这个必需的字段定义指令参数1。你可以使用这个字段来检验INS字段,或者用于输入数据。
Ø P2(1字节):这个必需的字段定义指令参数⒉你可以使用这个字段来检验INS字段,或者用于输入数据。
Ø Lc(1字节):这个可选的字段是命令的数据字段的字节数。
Ø 数据字段(可变的,字节Lc数):这个可选的字段保存命令数据。
Ø Le(1字节):这个可选的字段指定在期望响应的数据字段中的极限字节数
取决于命令数据的存在与否以及相应是否必须,命令APDU有四种变化。只有在你使用协议T = 0时,你才需要关心这些变化:
图3、APDU命令的四个可能的结构
一个典型的应用程序将以不同的结构方式使用不同的APDU命令。
响应APDU的格式很简单的:
图4、响应APDU
和一个APDU命令相似,响应APDU有可选择的和必要的字段:
Ø 数据字段(可变长度,由APDU命令中的Le确定):这个可选择的字段包含小应用程序返回的数据。
Ø SW1(1字节):这个必要的字段是状态字1。
Ø SW2(1字节):这个必要的字段是状态字2.
这些状态字的值在ISO 7816 - 4规范中定义:
Java Card框架应用编程接口中的ISO7816 Java接口定义了许多常数来帮助规范返回错误代码。
3、过程APDU
每当有一个进入的APDU用于所选择的小应用程序,JCRE就调用小应用程序的process ()方法,把进入的APDU作为一个参数传送。这个小应用程序必须解析APDU命令,处理数据、生成一个响应APDU,然后把控制权返回给JCRE。
RMI(JCRMI)通讯模型
第二种通信模型依靠J2SE RMI分布式对象模型的一个子集
在RMI模型中,一个服务器应用程序创建并生成可访问的远程对象,并且一个客户应用程序获得到远程对象的远程引用,然后调用它们的远程方法。在JCRMI中,Java Card小应用程序是服务器,而主应用程序是客户端。
JCRMI由类RMIService提供到扩展程序包javacardx.rmi中。JCRMI消息被封装到传入RMIService方法的APDU对象中,换句话说,JCRMI提供了一个基于APDU消息传递模型的分布式对象模型机制,通过这个机制服务器和客户端通信,来回传送方法信息、参数和返回值。
JavaCard虚拟机技术
Java Card虚拟机(JCVM)规范定义了Java程序设计语言的一个子集和一个用于智能卡的兼容Java的虚拟机,包括二进制数据表示和文件格式,以及JCVM指令集。
用于Java Card平台的虚拟机是两部分实现,一部分在卡外,一部分运行在卡本身。卡上的Java Card虚拟机解释字节码、管理类和对象等等。外部Java虚拟机部分是一个开发工具,一般称为Java Card转换工具,装载、检验和进一步地准备卡片小应用程序Java类,用于在卡上执行。转换工具输出的是一个Converted Applet(CAP)文件,这是一个包含一个Java程序包中所有类的文件。转换程序检验类是否遵循Java Card规范。
JCVM只支持Java程序设计语言的一个有限的子集,然而它保留了许多熟悉的特性,包括对象、继承、程序包、动态对象创建、虚拟方法、接口和异常。JCVM规范放弃了对许多语言元素的支持,因为这些语言元素可能会用掉很多智能卡本来就很有限的内存:
表格1、Java Card语言限制的摘要信息
语言特性 |
动态类装载、安全管理(java.lang.securitymanager)、线程、对象克隆和某些方面的程序包访问控制不支持。 |
关键字 |
不支持native、synchronized、transient、volatile、strictfp。 |
类型 |
不支持char、double、float和long,也不支持多维数组。对int的支持是可选的。 |
类和接口 |
不支持除了Object和Throwable以外的Java核心应用编程接口类和接口(java.io、java.lang、java.util),并且Object和Throwable的大部分方法不可用。 |
异常 |
一些Exception和Error子类被省去,因为它们封装的异常和错误不可能在Java Card平台上出现。 |
还有程序模型限制。例如一个装载库类不能再扩展到卡上;它隐含地成为final类型
为了符合存储限制,JCVM规范额外定义了许多程序属性的约束。表格4 JCVM资源限制总结。 注意这些约束中许多对于Java Card开发者来说是很明白的。
表格2、Java Card虚拟机约束的摘要信息
程序包 |
一个程序包可以引用128个其他的程序包 |
一个完全合乎要求的程序包名限于255字节以内。 注意字符大小取决于字符编码。 |
|
一个完全合乎要求的程序包名限于255字节以内。 |
|
类 |
一个类最多可以直接或者间接地实现15个接口。 |
一个接口最多可以继承于14个接口。 |
|
一个程序包如果包含小应用程序(一个小应用程序程序包),它最多可以有256个静态方法;如果没有小应用程序(库程序包),它最多只能有255个静态方法。 |
|
一个类最多可以实现128个public或者protected实例方法。 |
在Java Card虚拟机中,象在J2SE虚拟机中一样,class文件是核心,但是JCVM规范定义了两种其他文件格式来进一步使平台独立,转换小应用程序(Converted Applet,CAP)和导出(Export)格式,这将后面的文章中讲述。
虚拟机的生命周期
JCVM的生命周期与卡片本身的生命周期一致:在卡片制造并测试之后至发行到持卡人手中的一段时间内它就开始了生命周期,当卡片丢失或者毁坏的时候它的生命周期也就结束了。 卡片没有电力的时候JCVM也不会停止,因为它的状态被保存在卡片的非易失性存储器中。启动JCVM初始化JCRE并且创建所有的JCRE框架对象,这些在JCVM的整个生命周期都是运转着的。JCVM启动之后,与卡片所有的相互作用原则上都是被卡片上的某个小应用程序控制。 当卡片没电的时候,保存在RAM中的任何数据都会丢失,但是保存在永久性存储器中的任何状态都被保留。当再次加电以后,虚拟机又再次激活,这时虚拟机和对象的状态被恢复,并且重新开始执行等待进一步地输入。
JavaCard应用编程接口
Java Card应用编程接口规范定义了传统的Java程序设计语言应用编程接口的一个小的子集--甚至小于J2ME的CLDC。不支持字符串也不支持多线程。没有象Boolean和Integer这样的包装类,也没有Class和System类。
除Java核心类的小子集以外,Java Card框架还定义了它自己的特定支持Java Card应用程序的核心类。这些包含在下面的程序包中:
Ø java.io定义了一个异常类,基本的IOException类,来完成RMI异常层次。除此之外,没有包含其他传统的java.io类。
Ø java.lang定义了Object和Throwable类,但是没有J2SE中那么多方法。它还定义了许多异常类:Exception基本类,各种运行时间异常和CardException。除此之外,没有包含其他传统的java.lang类。
Ø java.rmi定义了Remote接口和RemoteException类。 除此之外,没有包含其他传统的java.rmi类。 对远程方法调用(Remote Method Invocation,RMI)的支持被包含来简化的移植并整合到使用Java Card技术的设备中。
Ø javacard.framework定义了组成核心Java Card框架的接口,类和异常。 它定义了重要的概念,例如个人识别号(Personal Identification Number,PIN),应用程序协议数据单元(Application Protocol Data Unit,APDU),Java Card小应用程序Applet,Java Card System(JCSystem)和一个utility类。 它还定义了各种ISO7816常数和各种Java Card特定的异常。 表格5总结了这些程序包的内容:
Table 5. 表格Java Card v2.2 javacard.framework
接口 |
ISO7816定义与ISO 7816-3和ISO 7816-4相关的常数。 |
MultiSelectable识别可以支持并发选择的小应用程序。 |
|
个人识别号码(PIN)描述一个被用于安全(验证)目的的个人识别号。 |
|
Shareable识别一个共享对象。能通过小应用程序防火墙的对象必须实现这个接口。 |
|
类 |
AID定义了一个遵循ISO7816-5与应用程序提供者关联的Application标识符;一个小应用程序必备的属性。 |
APDU定义了一个遵循ISO7816-4的应用程序协议数据单元,是小应用程序(卡上)和主应用程序(卡外)之间使用的通信格式。 |
|
小应用程序定义了一个Java Card应用程序。所有的小应用程序必须扩展这个抽象类。 |
|
JCSystem提供了控制小应用程序生命周期、资源和事务管理,和小应用程序内部对象共享和对象删除的方法。 |
|
OwnerPIN是PIN接口的一个实现。 |
|
Util提供用于操作数组和各种short的方法,包括arrayCompare()、arrayCopy()、arrayCopyNonAtomic()、arrayFillNonAtomic()、getShort()、makeShort()、setShort()。 |
|
异常 |
定义了各种的Java Card虚拟机异常类:APDUException、CardException、CardRuntimeException、ISOException、PINException、SystemException、TransactionException、UserException。 |
javacard.framework.service定义了用于服务的接口、类和异常。 服务处理APDU格式的进入的命令。 表格6总结了框架服务应用编程接口:
表格6. javacard.framework.service
接口 |
Service,基本的服务接口,定义了processCommand()、processDataIn()和processDataOut()方法。 |
RemoteService是一个普通Service,提供到卡上的服务的远程处理。 |
|
SecurityService扩展了Service基本接口,并且提供了查询当前安全状况的方法,包括isAuthenticated ()、isChannelSecure ()和isCommandSecure ()。 |
|
类 |
BasicService是一个服务的默认实现;它提供帮助方法来处理APDU和服务协作。 |
Dispatcher维护一个服务的注册。如果你想委托一个APDU的处理到几个服务上,你可以使用一个dispatcher。 一个dispatcher可以使用process ()方法完整的处理一个APDU,或者使用dispatch ()方法把它发送到几个服务上让其处理。 |
|
异常 |
ServiceException一个服务相关的异常 |
javacard.security定义了用于Java Card安全框架的类和接口。 Java Card规范定义了一个强健的安全应用编程接口,包括各种型式的私钥和公钥及其算法、用于计算循环码校验(CRCs)的方法、消息摘要和签名:
表格7. javacard.security
接口 |
普通的基本接口Key,PrivateKey、PublicKey和SecretKey,以及描述各种类型安全密钥和算法的子接口:AESKey、DESKey、DSAKey、DSAPrivateKey、DSAPublicKey、ECKey、ECPrivateKey、ECPublicKey、RSAPrivateCrtKey、RSAPrivateKey、RSAPublicKey |
类 |
Checksum:用于循环冗余码校验算法抽象基本类 |
KeyAgreement:用于秘钥约定算法的基本类 |
|
KeyBuilder:秘钥-对象工厂 |
|
KeyPair:一个保存一对秘钥的容器,一个私钥一个公钥 |
|
MessageDigest:用于散列算法的基本类 |
|
RandomData:用于生成随机数的基本类 |
|
Signature:用于签名算法的基本抽象类 |
|
异常 |
CryptoException:与加密有关异常,比如不支持的算法或者未初始化的秘钥。 |
javacardx.crypto是一个扩展程序包,定义了接口KeyEncryption和Cypher类,都在自己的程序包中,便于控制导出。使用KeyEncryption来解密一个使用加密算法的输入秘钥。 Cypher是所有的密码必须实现的基本抽象类
CardRemoteObject定义两个方法export()和unexport(),允许或者禁止从卡外到对象的远程访问。RMIService扩展了BasicService,并且实现RemoteService来处理RMI请求。
安全和信任服务应用编程接口(SATSA)
定义在JSR177中的SATSA,指定一个提供用于J2ME的安全和信任应用编程接口的可选程序包。客户端应用编程接口提供了到通过一个安全元素(例如一张智能卡)提供的服务的访问,包括敏感信息的安全存储与检索,以及加密和验证服务。
SATSA利用定义在CLDC 1.0版本中的普通连接框架(GCF)来提供到消息传递和JCRMI通信模型的更抽象的接口。为了支持信息传送,SATSA定义了APDU:URL模式和APDUConnection, 并且为了支持JCRMI,它定义了JCRMI:模式和JavaCardRMIConnection
SATSA有下面的程序包组成:
java.rmi定义了Java2标准版java.rmi程序包的一个子集,特别是Remote和RemoteException
javacard.framework定义了一个远程方法可能抛出的标准Java Card应用编程接口异常:CardRuntimeException、ISOException、APDUException、CardException、PINException、SystemException、TransactionException和UserException
javacard.framework.service定义了远程的方法可能抛出的一个标准的Java Card应用编程接口服务异常:ServiceException
javacard.security定义了一个远程方法可能抛出的标准的Java Card应用编程接口与加密相关的异常:CryptoException
javax.microedition.io定义了两个连接子接口,APDUConnection用于基于APDU协议的智能卡的访问,JavaCardRMIConnection用于Java Card RMI协议。
javax.microedition.jcrmi定义了Java Card RMI stub编译程序生成的stub使用的类和接口
javax.microedition.pki定义了用于用户证书基本管理的类。
javax.microedition.securityservice定义了用于生成应用程序级别的数字签名的类。
Java Card运行时环境
JCRE规范定义了Java Card虚拟机的生命周期,小应用程序生命周期,小应用程序如何被选择并相互隔离,事务和对象持久性和共享。这JCRE提供一个平台无关的接口到卡片的操作系统提供的服务。它由Java Card虚拟机、Java Card应用编程接口和任何特定供应商的扩展组成:
图Java Card体系结构和运行时环境
JavaCard小应用程序
Java Card平台是一个安全的多应用环境-许多来自不同供应商的不同的小应用程序可以在同一张卡片上安全地共存。每个小应用程序被指派给一个执行上下文,这个上下文控制到分配给它的对象的访问。
一个执行上下文和另一个执行上下文之间的界限经常被称为小应用程序防火墙( applet firewall)。它是Java沙箱安全概念的一个Java Card运行时间改进本,联合类装入器java.ClassLoader和访问控制器、 java.AccessController的功能。Java Card防火墙创建了一个虚拟堆,这样一个对象只能访问存在于相同的防火墙内的(公共的)方法和数据。 一个防火墙可能包含许多小应用程序及其他对象,比如公共的秘钥。一个Java Card执行上下文目前作用域是程序包。 当每个对象被创建的时候,它被指派去执行调用程序的上下文。
Java Card平台支持跨防火墙的安全对象共用。图表12描述小应用程序隔离和对象共用
图表1. 小应用程序防火墙和对象共用
典型的流程,如图表12中的描述:
请求通过调用系统的JCSystem.getAppletShareableInterfaceObject ()方法访问Appletc的共享接口。
由于Appleta,JCRE通过调用小应用程序的getShareableInterfaceObject ()方法来要求Appletc的可共享的接口。
如果Appletc允许共用,Appleta将获得一个Appletc的共享对象的引用。Appleta现在就可以访问Appletc了。 Appleta将拥有它创建的任意对象,即使是那些定义在Appletc的。
在同一个执行上下文中的小应用程序默认情况下能够相互访问,所以Appleta和Appletb不需要遵循这个程序来共享对象。
管理内存和对象
在一个Java Card设备中,内存是最重要的资源。 在一些Java Card中,实现一个垃圾收集程序可能不能使用。当一个对象被创建的时候,对象和它的内容被保存在非易失性存储器中,使之可在会话之间使用。在某些情况下,应用程序数据不需要持久- -它是暂时的或者瞬变的(transient)。为了减少智能卡的持久性内存的消耗,并且最大化它的生命周期,我们要尽可能的经常以transient更新数据。
Java Card技术不支持关键字transient。取而代之,Java Card应用编程接口(javacard.framework.JCSystem)定义了三个方法,允许你在运行时间创建transient数据,还定义了一个方法让你检查一个对象是否是transient的:
static byte[] makeTransientByteArray(short length, byte event)
static Object makeTransientObjectArray(short length, byte event)
static short[] makeTransientShortArray(short length, byte event)
static byte isTransient(java.lang.Object theObj)
你可以创建一个瞬变的字节或者short基本数据类型的数组,你也可以创建一个瞬变Object。但是记住下面用于瞬变数据的行为:
一个瞬变对象的状态在会话之间不能持久保存。 注意内容(不是对象本身)是什么是瞬变的。和任何其他的Java语言对象一样,一个瞬变对象只要它被引用就一直存在。
当一个事件例如卡片复位或者小应用程序取消选择发生的时候,一个瞬变对象的内容可能重置为字段的缺省值(0、false或者null)。
因为安全的理由,瞬变对象的字段不被保存在持久内存中。
对瞬变对象字段的更新不是原子性的,不会受事务的影响。
在一个Java Card环境中,数组和基本类型应在对象声明中声明,并且你应该最小化对象实例化,以利于对象重用。实例化对象在小应用程序生命周期中只有一次,最好在小应用程序的初始化阶段,在小应用程序生命周期中只被调用一次的install()方法中。
为了促进对象的重用,对象应该保持在小应用程序的生命周期的范围内或引用中,并且它们的状态(成员变量的值)在重用之前根据情况重置。 因为垃圾收集程序并不总是可用的,一个应用程序可能从不回收分配给不太占用内存的对象的存储器。
持久的事务
JCRE支持原子事务,原子事务安全地更新一个或多个持久对象。如果发生掉电或者程序错误等情况,事务将保护数据的完整性。 事务是在系统级支持的,通过下面的方法:
JCSystem.beginTransaction()
JCSystem.commitTransaction()
JCSystem.abortTransaction()
在一个为许多事务模型所共用的模式中,一个Java Card事务以对beginTransaction()的调用开始,以对commitTransaction()或者abortTransaction()的调用结束。 让我们来看看使用这些应用程序编程接口的代码片断:
…
Private short balance;
…
JCSystem.beginTransaction();
balance = (short)(balance + creditAmount);
JCSystem.commitTransaction();
…
实例变量balance的更新是为了保证一个原子操作。 如果一个程序错误或者电力重置等事件发生,这个事务就会保证前面的balance值余额被恢复。
JCRE不支持嵌套事务。
JavaCard小应用程序的生存周期
卡片上的每个小应用程序由一个Application标识符(AID)唯一标识。 定义在ISO 7816 - 5中的AID是一段5到16字节之间的序列。 所有的小应用程序必须扩展Applet抽象基本类,这个类定义了JCRE使用的方法来控制小应用程序的生存周期,如图10概括:
小应用程序生命周期方法
小应用程序生存周期在小应用程序被下载到卡片中并且JCRE调用小应用程序的static Applet.install ()方法的时候开始,并且小应用程序通过调用Applet.register ()在JCRE中注册。 一旦小应用程序被安装并且注册,它处于未选择的状态,可以进行选择并且处理APDU。 图表11.总结小应用程序方法的操作。
图表2、使用 Java Card小应用程序方法
当处在未选择的状态的时候,小应用程序是非激活状态。当主应用程序要求JCRE选择一个卡片中特定的小应用程序的时候(通过指示读卡器发送一个SELECT APDU或者MANAGE CHANNEL APDU),一个小应用程序被选择进行APDU处理。为了通知这个小应用程序主应用程序已经选择了它,JCRE调用它的select()方法;小应用程序一般执行相应的初始化来为进行APDU处理做准备。
一旦选择,JCRE传送输入的APDU命令到小应用程序,通过调用它的process()方法来进行处理。JCRE捕捉任何小应用程序没能捕捉的异常。
当主应用程序告诉JCRE选择另一个小应用程序的时候,前一个小应用程序取消选择。 JCRE通知活动的小应用程序,它已经通过调用它的deselect()方法被取消了选择,小应用程序回到不活动的未经选择的状态。
Java Card会话和逻辑通道
卡片会话是卡片被加电并且和读卡器交换APDU的一段时间。
Java Card 2.2支持逻辑通道(logical channels)的概念,允许最多智能卡中的16个应用程序会话同时开启,每个逻辑通道一个会话。因为卡片中的APDU的处理不能中断,并且每个APDU包含一个到逻辑通道(在CLA字节)的引用,变动的APDU可以拟同步地访问卡片上的许多小应用程序。你可以设计一个小应用程序被多次选择;也就是说,每次和一个以上逻辑通道通信。多选的小应用程序必须实现javacard.framework.MultiSelectable接口和相应方法。
在一些卡片部署中,一个默认小应用程序可以被定义为在卡片复位以后被自动地选择,用于在基本逻辑通道(通路0)上通信。Java Card 2.2允许你定义默认小应用程序,但是不指定的如何做;其机理由厂家特定。
结束语
使用Java Card技术的智能卡是携带数字个人信息和计算能力的最便携和安全的方法;它是一个今天数字世界中非常强大的并且必要的技术。
本文主要是关于JavaCard的基础知识:利用智能卡存储敏感信息和安全地处理事务,以及JavaCard技术的各个的方面- Java Card虚拟机、运行时环境、有关的应用程序编程接口和Java Card小应用程序的行为。
以后的专题中我们将讲述Java Card技术的开发