Java Card CAP文件分析
来源:互联网 发布:过期备案域名 编辑:程序博客网 时间:2024/05/25 23:28
JAVA 智能的可执行文件(CAP 文件)是编译多个应用程序(Applet)的生成结果,包含了一个包中定义的所有类和接口,与包之间是一一对应的关系。实际发卡操作时,首先需要将该可执行文件下载至卡片中,并安装需要的应用实例;用户使用该安装的应用实例执行操作功能。
CAP文件包含12个组件:
Component Type
Value
COMPONENT_Header
1
COMPONENT_Directory
2
COMPONENT_Applet
3
COMPONENT_Import
4
COMPONENT_ConstantPool
5
COMPONENT_Class
6
COMPONENT_Method
7
COMPONENT_StaticField
8
COMPONENT_ReferenceLocation
9
COMPONENT_Export
10
COMPONENT_Descriptor
11
COMPONENT_Debug
12
注意:
一个完整的CAP文件,除Applet、Export 和Debug组件是可选外,其他均为必选。每个组件封装成一个CAP包,包含在Jar包中。最后在卡上只保留了5个组件:COMPONET_Method,COMPONET_Class,COMPONET_ConstantPool,COMPONET_StaticField和 COMPONET_Export。其余的组件只是安装时提取有用信息而不在卡中保存。
12个组件中,类class组件保存本应用声明的所有类和接口的信息; 方法method组件保存本应用声明的所有方法和接口,method中利用2字节索引index引用类、方法和域;常数池constant pool组件保存method组件引用的所有类、方法和域信息,分为类、实例域、虚方法、父方法、静态域和静态方法6类,每组信息为4个字节;相关地址reference location组件保存method组件中索引的偏移。
对于JavaCard而言,应用程序的下载过程是即CAP文件写入到EEPROM的过程,即是对CAP文件的下载过程。在CAP文件的下载过程中,需要将一部分组件进行解析,同时对reference location中指定的位置进行链接,能够链接到method组件中的一个索引号,并根据索引号查找constant pool中保存的、与该索引号对应的类、方法或域在 EEPROM中的实际地址,调用实际地址中存储的数据。也就是说,方法的调用其实是需要两个步骤来实现的:
- 根据reference location中指定的位置进行链接,获取method组件中的索引号;
- 根据索引号查找constant pool中保存的、与该索引号对应的类、方法或域在EEPROM中的实际地址,调用实际地址中存储的数据。
查看一个CAP文件的组件,可以通过两种方法实现:
- 解压缩软件直接解压得到
- 通过JCK中的capdump将其分解成各个组件
下面是加压cap的java源码:
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.util.ArrayList;
- import java.util.Enumeration;
- import java.util.List;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipFile;
- import android.os.Environment;
- import android.util.Log;
- public class Cap {
- static final String TAG = "cap";
- static public final String CAP_DIRECTORY = "//mnt//sdcard//cap//";
- static final int READ_LENGTH = 1024;
- private List<String> mCapFileList;
- public void loadCapFile(String CapFileName) {
- try {
- if (!Environment.getExternalStorageState().equals(
- Environment.MEDIA_MOUNTED)) {
- Log.e(TAG, "SD card not available!");
- return;
- }
- File file = new File(CAP_DIRECTORY + CapFileName);
- if (!file.exists()) {
- Log.e(TAG, CAP_DIRECTORY + "safe.cap not available!");
- return;
- }
- mCapFileList = new ArrayList<String>();
- mCapFileList.clear();
- BufferedOutputStream dest = null;
- BufferedInputStream is = null;
- ZipEntry entry;
- ZipFile zipfile = new ZipFile(file);
- Enumeration<? extends ZipEntry> e = zipfile.entries();
- while (e.hasMoreElements()) {
- entry = (ZipEntry) e.nextElement();
- String fileName = entry.getName();
- if (fileName.endsWith(".MF"))
- continue;
- if (fileName.contains("/")) {
- int dir = fileName.lastIndexOf("/");
- String root = CAP_DIRECTORY + fileName.substring(0, dir);
- File path = new File(root);
- if (!path.exists()) {
- path.mkdirs();
- }
- }
- int count;
- byte data[] = new byte[READ_LENGTH];
- mCapFileList.add(CAP_DIRECTORY + entry.getName());
- FileOutputStream fos = new FileOutputStream(CAP_DIRECTORY
- + entry.getName());
- dest = new BufferedOutputStream(fos, READ_LENGTH);
- is = new BufferedInputStream(zipfile.getInputStream(entry));
- while ((count = is.read(data, 0, READ_LENGTH)) != -1) {
- dest.write(data, 0, count);
- }
- dest.flush();
- dest.close();
- is.close();
- fos.close();
- }
- } catch (Exception e) {
- Log.e(TAG, "loadCap: " + e.getMessage());
- }
- }
- public List<String> getCapFileList() {
- return mCapFileList;
- }
- }
使用方法
- Cap cap = new Cap();
- cap.loadCapFile("HelloWorld.cap");
所有的组件均有通用结构格式,如下:
- component {
- u1 tag //u1表示无符号单字节类型的数据变量类型;tag为组件索引号,按照上面组件名称的顺序从1至12排列
- u2 size //u2表示无符号双字节的数据变量类型;size为可变长度数组info[]的元素个数
- u1 info[] //数组info[]中含了组件的所有信息,依据各组件属性不同而各不相同
- }
比如Applet.cap的十六进制数据是:
0300090105c0c1c2c3c40085
第一个03是tag,然后是0009是size,说明info为9个字符,01标示了这是包中的第一个applet,05为该Applet的AID的长度,后面的c0c1c2c3c4即为applet的AID,后面的0085是该Applet的install_method_offset,即当前Applet中的install()在Method组件info[]中的偏移。
推荐的CAP组件安装顺序:
- COMPONENT_Header
- COMPONENT_Directory
- COMPONENT_Import
- COMPONENT_Applet
- COMPONENT_Class
- COMPONENT_Method
- COMPONENT_StaticField
- COMPONENT_Export
- COMPONENT_ConstantPool
- COMPONENT_ReferenceLocation
- COMPONENT_Descriptor (optional)
COMPONENT_Debug组件不需要下载到卡内。
作者:fish
转载:http://www.dreamingfish123.info/?p=818
- Java Card CAP文件分析
- Java Card CAP文件分析
- Java Card CAP 文件组件分析 00
- Java Card CAP 文件组件分析
- JAVA card 应用开发(四) Java Card CAP 文件组件分析
- Java Card CAP 文件组件分析 01—— Header Component
- Java Card CAP 文件组件分析 02—— Directory Component
- Java Card CAP 文件组件分析 03—— Applet Component
- Java Card CAP 文件组件分析 04—— Import Component
- Java Card CAP 文件组件分析 05—— Constant Pool Component
- Java Card CAP 文件组件分析 09—— Reference Location Component
- Java Card CAP 文件组件分析 10—— Export Component
- Java Card CAP 文件组件分析 12—— Debug Component
- Java Card CAP组件分析——Header Component
- Java Card CAP组件分析——Header Component
- JAVA card 应用开发(三) 把APPLET(CAP文件)装载到卡片
- JAVA card 应用开发(三) 把APPLET(CAP文件)装载到卡片
- JAVA card 应用开发(三) 把APPLET(CAP文件)装载到卡片
- PHP计划任务:如何使用Linux的Crontab执行PHP脚本
- Unity手游之路<七>角色控制器
- java错误记录
- Solr搜索的排序打分规则探讨
- VBScript实现IE浏览器直接打印功能
- Java Card CAP文件分析
- Windows API遍历文件目录、搜索文件
- php常用命令
- Java Card CAP组件分析——Header Component
- KEIL MDK 查看代码量、RAM使用情况--RO-data、RW-data、ZI-data的解释
- linux下QQ如何使用
- 我的二脑
- XML命名空间深度解析 —— 命名空间简介
- BZOJ2002弹飞绵羊