资源描述
EMV Applet系统设计说明
1.概述
本Applet是根据《EMV Integrated Circuit Card Specifications for Payment Systems v4.3》及《Visa Integrated Circuit Card Specification》系列国际规范,基于NXP的JCOP平台,开发的用于金融交易的软件产品。
本Applet运行的平台要求:支持JAVA CARD 2.2.1及以上版本、Global Platform v2.1.1及以上版本的JAVA 虚拟机。
个人化按照规范《EMV Card Personalization Specification v1.1》,采用《Global Platform Card Specification v2.1.1》规范中定义的Store data命令,使用DGI作为数据分组标识。能够达到快速发卡,可二次发卡的功能。
2.包(Package)
本Applet包的设计可以有两种方式供选择:
1. 单package设计:即所有类都在一个包中,优点是整个工程结构简单,程序运行时减少包与包之间变量传递等,减低效率损耗,缺点是文件系统部分没有单独做一个package,不能以后直接拿出来给其它applet使用;
2. 双package设计:即文件系统单独做一个包,功能部分做另一个包,其优缺点跟单package是对应的,即可能会使结构复杂,增加效率损耗,优点是文件系统如果设计的比较全面,可以在以后其它applet中拿来直接使用。
在本Applet中,倾向于选择第一种,单package设计,因为以后的applet对文件系统的需求并不确定,目前设计文件系统不一定完全满足需求,或者不需要这么大的系统,反而生成的cap文件占用了较大的卡片空间。
以下对采用单Package设计包含的类结构进行大致描述:
com.bhz.emv
API
Common
EMVApplet
RecordFile
图1 类结构图
以下将对各个类分别进行描述。
3.EMVApplet类
本类的声明如下:
public class EMVApplet extends Applet implements Application,AppletEvent
本类是本软件中最重要的类。在本类中,要完成所有EEPROM空间的申请,包括文件创建和密钥体创建等;要对个人化写入的数据进行处理,分别写入对应的记录文件、数据对象或密钥对象中;此外,更重要的是,本类还要实现所有APDU命令的处理。
3.1EMVApplet构造方法
EMVApplet构造方法定义本类中需要用到的全局变量,创建其它类的实例,创建所有文件和密钥、PIN都在此方法中完成。其中密钥方面,对称密钥(3DES密钥)可以直接使用buildkey进行创建,RSA密钥位数在Common类中已经进行配置,直接创建对象;此外,PIN值、长度、最大重试次数也已经在Common中定义了常量。
记录文件的创建也在此方法中完成,举例:
RecordFile[] EF;
EF[0] = new RecordFile((short)0x01,(short)800,(byte)UNDER_PSE);
EF[1] = new RecordFile((short)0x02,(short)500,(byte)UNDER_ADF);
密钥对象的创建举例:
RSA_PriK_Crt =(RSAPrivateCrtKey)KeyBuilder.buildKey(
KeyBuilder.TYPE_RSA_CRT_PRIVATE,
Common.RSA_KEY_LENGTH,
false);
为了提高交易效率,以下个人化阶段写入的变量在本类中定义初始值:
TAG
变量定义
9F36
Public byte[] ATC
9F13
Public byte[] LAST_ONLINE_ATC
9F27
Public byte CID
9F10
Public byte[] ISS_APP_DATA
表1 EMVApplet中定义的交易数据对象
3.2Process和ProcessData方法
Process方法是所有APDU的命令入口,进入各条命令处理之前,应用需要做一些卡片生命周期判断。
ProcessData主要是处理个人化阶段STORE DATA命令传递进来的数据,我们需要做的是接收数据,获取DGI标识,分别写入对应的记录或其它预先定义的变量中。对于RSA私钥和DES密钥,需要密文传入,卡内要知道此用于密钥解密的密钥,写入对象前解密。DGI与对象的对应表如下:
DGI
名称
类型
用途
0B01
PSE下DIR文件
记录,只有一条记录的记录文件中
写入DIR信息
0101
EF[0]第一条记录
记录
写交易数据,通过readrecord返回给终端
0102
EF[0]第二条记录
记录
写交易数据,通过readrecord返回给终端
0103
EF[0]第三条记录
记录
写交易数据,通过readrecord返回给终端
0201
EF[1]第一条记录
记录
写交易数据,通过readrecord返回给终端
0202
EF[1]第二条记录
记录
写交易数据,通过readrecord返回给终端
0203
EF[1]第三条记录
记录
写交易数据,通过readrecord返回给终端
0204
EF[1]第四条记录
记录
写交易数据,通过readrecord返回给终端
0205
EF[1]第五条记录
记录
写交易数据,通过readrecord返回给终端
0206
EF[1]第六条记录
记录
写交易数据,通过readrecord返回给终端
0301
EF[2]第一条记录
记录
写交易数据,通过readrecord返回给终端
0302
EF[2]第二条记录
记录
写交易数据,通过readrecord返回给终端
0401
EF[3]第一条记录
记录
写交易数据,通过readrecord返回给终端
0501
EF[4]第一条记录
记录
写交易数据,通过readrecord返回给终端
0502
EF[4]第二条记录
记录
写交易数据,通过readrecord返回给终端
8000
三条DES密钥密文
DES对象数据
解密后,分别写入三个密钥对象
9001
RSA私钥的P,密文
RSA私钥元素
解密后,写入RSA私钥对象
9002
RSA私钥的Q,密文
RSA私钥元素
解密后,写入RSA私钥对象
9003
RSA私钥的Dp,密文
RSA私钥元素
解密后,写入RSA私钥对象
9004
RSA私钥的Dq,密文
RSA私钥元素
解密后,写入RSA私钥对象
9005
RSA私钥的U,密文
RSA私钥元素
解密后,写入RSA私钥对象
表2 个人化数据分组标识
3.3所有命令的实现
本类中还包括一些命令实现,要实现的命令如下:
1、 SELECT命令(*编码规范中建议方法首字母小写,对process中处理命令的方法是否首字母大写以区分?)
声明:private void SelectFile(APDU apdu)
2、 READRECORD
声明:private void ReadRecord(APDU apdu)
3、 GETCHALLENGE
声明:private void GetChallenge(APDU apdu)
4、 VERIFY
声明:private void Verify(APDU apdu)
5、 GETDATA
声明:private void GetData(APDU apdu)
6、 APP_BLOCK
声明:private void AppBlock(APDU apdu)
7、 APP_UNBLOCK
声明:private void AppUnblock(APDU apdu)
8、 CARD_BLOCK
声明:private void CardBlock(APDU apdu)
9、 UPDATA_RECORD
声明:private void UpdateRecord(APDU apdu)
10、GET_PROCESSING_OPTIONS
声明:private void GetProcessOption(APDU apdu)
11、GENERATE_AC
声明:private void GenerateAC(APDU apdu)
12、INTER_AUTH
声明:private void InterAuth(APDU apdu)
13、EXTER_AUTH
声明:private void ExterAuth(APDU apdu)
14、PIN CHANGE/UNBLOCK
声明:private void PinChangeUnblock(APDU apdu)
15、PUT_DATA
声明:private void PutData(APDU apdu)
对本命令,有以下两种情况:
CLA值
命令描述
04
按照Visa规范处理。
80
用于个人化的私有命令,非个人化阶段,此命令无效。主要用于更新表1和表5定义的所有交易数据对象,其中P1,P2代表要修改的对象TAG,若TAG为1字节,则P1为00,P2为TAG值;若TAG为2字节,P1代表TAG第一字节,P2代表TAG第二字节。数据域为要修改的新值,不需要带MAC。由于此命令属于应用实现的私有命令,应该在第7章的个人化流程结束后,进入应用后,执行此命令修改数据对象。
3.4其它主要方法
本小节描述本类中主要实现的方法,见下表:
主要方法
描述
protected EMVApplet(byte[] bArray, short bOffset, byte bLength)
构造方法
public void GAC1(APDU apdu)
第一条GAC命令的实现
Public void GAC2(APDU apdu)
第二条GAC命令的实现
private void buildReturnData(APDU apdu,byte[] inbuffer,short ModulusLen)
GAC命令返回响应数据的组织
表3 EMVApplet的主要方法
4.RecordFile类
本Applet出于高效的考虑,不创建文件系统,在使用选择命令选择PSE和ADF时,给出正确的响应即可。但记录文件类型的EF实体作为主要的数据载体还是要创建的。本类是记录文件的实现,其成员定义如下:
公有属性:
short sfi,size;文件的SFI和大小;
byte data[];记录内容;
byte tag;在哪个ADF下标志,主要是处理不同DF下具有相同SFI的情况
构造方法如下:
RecordFile(short SFI,short LEN,byte tag)
{
This.sfi = SFI;
This.size = LEN;
This.tag = 0;//编码时使用static final 常量定义在ADF下还是PSE下。
Data = new byte[LEN];
}
在RecordFile类中,各条记录长度不等,都按照LV的格式依次排列,物理结构上相当于二进制文件,Record长度统一使用1字节表示。举例:
Record1长度
Record1值
Record2长度
Record1值
……
其它主要方法:
Public void updateRecord(short recnumer,byte[] buf,short offset,short recordlen)
Public short readRecord(short recnumber,byte[] buf,short offset)
本类为每个记录文件分配一整段空间,在记录文件第一次执行updateRecord写记录内容时,将按照上表的方式,依次写入各条记录的长度和内容,如果某条记录已经被写入了内容,再次执行updateRecord,必须写入与原记录长度相等的数据,否则不允许写入。
5.API类
本类实现所有需要进行加密、签名、计算过程密钥的方法,除此外,还实现很多功能性方法,与类成员无关,可被静态调用的方法,譬如判断某字节某位是否为1的方法等,数量很多,这里不一一描述。
主要方法如下:
主要方法
描述
public generateSessionKey(DESKey mk)
根据输入的密钥生成过程密钥
public calculateMAC(byte[] inBuff,short inOffset,short inLength)
计算MAC
public short rsaSignature(byte[] inBuff,short inOffset,short inLength,byte[] outBuff,short outOffset)
计算RSA签名
public short des(DESKey key,byte[] inbuf,short,inoff,byte[] outbuf,short outoff,boolean tag)
DES加密和解密
public boolean isBitTrue(byte bByte, byte bitnumber )
判断某字节某位是否为1
表4 Algorithm的主要方法
6.Common类
本类定义了常用的变量,其它类使用静态调用的方法调用本类成员和方法。同时,本类还起到配置文件的作用,当有定制需求时,一些配置项可以在本类定义的静态常量进行设置。主要定义内容举例如下:
public static final byte[] PSE =
{ byte)0x31,(byte)0x50,(byte)0x41,(byte)0x59, (byte)0x2E,(byte)0x53,(byte)0x59,(byte)0x53, (byte)0x2E,(byte)0x44,(byte)0x44,(byte)0x46, (byte)0x30,(byte)0x31};
public static final byte[] ADF =
{ (byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x03, (byte)0x33,(byte)0x10, (byte)0x10};
public static final short RSA_KEY_LENGTH = (short)1024;
public static final short PIN_LENGTH = (short)3;
public static final short PIN_TRY_TIMES = (short)3;
public static final byte[] PIN = {(byte)0x24,(byte)0x12,(byte)0x34};
为了方便代码搜索,状态码需要自定义的也在本类中进行定义,举例如下:
Public static final short WRONG_6F01 = (short)0x6F01;
直接对数据对象的访问能大大提高交易速度,因此,针对某一种发卡模板,在代码中直接定义下列数据对象的值,如果改为其它模板的发卡,使用私有命令PUT_TRANSDATA修改即可。定义举例如下:
public byte[] AIP ={(byte)0x7C,(byte)0x00};
public byte[] AFL=
{(byte}0x08,(byte)0x01,(byte)0x03,(byte)0x00,(byte)0x10,(byte)0x01,(byte)0x03,(byte)0x01);
本表格总结所有需要在本类中定义的交易数据对象:
TAG
对象声明
9F55
Public static byte GEO_INDICATOR
82
Public static byte[] AIP
94
Public static byte[] AFL
87
Public static byte APP_PRIORITY_INDICATOR
9F08
Public static byte[] APP_VERSION_NUM
9F56
Public static byte ISS_AUTH_INDICATOR
8C
Public static byte[] CDOL1
8D
Public static byte[] CDOL2
9F0D
Public static byte[] ISS_ACTION_CODE_DEFAULT
9F0E
Public static byte[] ISS_ACTION_CODE_DENIAL
9F0F
Public static byte[] ISS_ACTION_CODE_ONLINE
5F28
Public static byte[] ISS_COUNTRY_CODE
5F2D
Public static byte[] LANGUAGE_PREFRENCE
9F51
Public static byte[] APP_CURRENCY_CODE
50
Public static byte[] APP_LABLE
9F07
Public static byte[] AUC
8E
Public static byte[] CVM_LIST
9F49
Public static byte[] DDOL
9F52
Public static byte[] ADA
5F34
Public static byte PAN_SEQUENCE_NUMBER
5F30
Public static byte[] SERVICE_CODE
5F24
Public static byte[] APP_EFFECTIVE_DATE
5F25
Public static byte[] APP_EXPIRATION_DATE
9F14
Public static byte LOWER_CON_OFFLINE_LIMIT
9F23
Public static byte UPPER_CON_OFFLINE_LIMIT
表5 Common定义的数据交易对象
7.个人化数据处理
7.1卡片处理
本节主要介绍个人化过程中,数据传入后,Applet内部的处理流程,主要是以下两个步骤:
1、 在EMVApplet中先创建记录文件,每个文件被分配了一整块连续空间,详情见第4章。
在ProcessData中,接收STORE DATA命令传进来的命令,先辨别DGI,按照DGI第一个字节为SFI,第二字节为记录号的方式,调用RecordFile类中的updateRecord方法,示例代码如下:
EF[0]. updateRecord((short)0x01, buf,(short)offset ,(short)recordlen )
2、 除了要写入记录中的数据,还包括RSA私钥、DES密钥、DF的FCI等数据,这些也需要预先在EMVApplet类构造函数中提前分配EEPROM空间,辨别到对应的DGI后,为各对象写值。
7.2个人化流程
整个个人化流程使用《Global Platform Card Specification v2.1.1》中定义的以下命令,不需要在应用中实现。直到Store Data最后一条,个人化结束,进入应用。
1、 Select Card Manager
本命令是选择卡片管理器命令,卡片管理器作为卡片的管理枢纽,被规划为具备多重职责。选择成功后,即可为应用打开一些全局服务,APDU如下:
00A4040008A000000003000000
命令执行成功后,返回9000和响应数据
2、Initilize Update
3、External Authenticate
这两个命令先后执行,在安全通道初始化过程中,起到主机认证并决定后续命令安全级别的作用。
4、Install for personalization (GP v2.1.1及以上版本)
此命令数据域为某一个应用的AID,后续的STORE DATA命令将为此应用进行个人化。
5、Store Data命令
此命令用来向上一条命令中指定的应用传递个人化数据。
6、Put Data 应用私有个人化命令
修改指定数据对象。
10
展开阅读全文