在JavaCard Classic上读取TLV编码数据

时间:2016-02-19 15:16:55

标签: javacard tlv jcop

我想在Java卡上阅读TLV编码证书(NXP JCOP J3D081,JCOP版本2.4.2,Java Card版本3.0.1 Classic)。

成功创建了cap文件,但是当我尝试在卡上安装它时,我收到了一个gpshell错误:

  

load()返回0x80206A80(6A80:命令数据中的数据错误/错误值。)

我使用JCDK 3.0.3中的jar,这通常适用于像椭圆曲线等的东西。与TLV的东西有什么不同?

使用的applet代码(不使用BERTLV时安装正常):

package org.thomas;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Util;
import javacardx.framework.tlv.BERTLV;
import javacardx.framework.tlv.ConstructedBERTLV;

public class TlvApplet extends Applet {

    private ConstructedBERTLV certificate;
    byte[] certificateLength = new byte[2];

    /**
     * TlvApplet constructor
     * 
     * @constructor
     */
    private TlvApplet() {

        // Register with the JCRE
        register();
    }

    /**
     * Installs 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 TlvApplet();
    }

    public void process(APDU apdu) throws ISOException {

        byte buffer[] = apdu.getBuffer();
        short incomingLength = apdu.setIncomingAndReceive();

        certificate = (ConstructedBERTLV) BERTLV.getInstance(buffer,
            ISO7816.OFFSET_CDATA, incomingLength);


        certificateLength[0] = (byte) (certificate.size() & 0xff);
        certificateLength[1] = (byte) ((certificate.size() >> 8) & 0xff);

        Util.arrayCopyNonAtomic(certificateLength, (short) 0, buffer,
            ISO7816.OFFSET_CDATA, (short) 2);

    }

}

我使用以下ant build.xml创建了cap文件:

<?xml version="1.0" encoding="UTF-8" ?>
<project default="convert" name="Create JC 3 applet" basedir=".">
<property environment="env" />

<!-- Include properties in the build.properties file -->
<property file="build.properties" />

<!-- Build specific properties -->
<property name="source.path" location="${basedir}/${source.folder}" />
<property name="jcdk.libs" location="${basedir}/${jcdk.basefolder}/${jcdk.subfolder.libs}" />
<property name="jcdk.apiexports" location="${basedir}/${jcdk.basefolder}/${jcdk.subfolder.apiexportfiles}" />
 <property name="target.path.classes"
location="${basedir}/${target.basefolder}/${target.subfolder.classes}" />
<property name="target.path.cap"
location="${basedir}/${target.basefolder}/${target.subfolder.applet}" />

<!-- set the classpath for the tasks and the API, include all jar files -->
<path id="classpath" description="Sets the classpath to Java Card API and tools">
    <fileset dir="${jcdk.libs}">
        <include name="*.jar" />
    </fileset>
</path>

<!-- set the export path to the Java Card export files -->
<path id="export" description="set the export file path">
    <fileset dir="${jcdk.apiexports}">
        <include name="**/*.exp" />
    </fileset>
    <pathelement path="${jcdk.apiexports}" />
    <pathelement path="${target.path.classes}" />
</path>

<path id="capexport" description="set the export file for the cap path">
    <fileset dir="${jcdk.apiexports}">
        <include name="**/*.exp" />
    </fileset>
    <pathelement path="${jcdk.apiexports}" />
</path>

<!-- Definitions for tasks for Java Card tools -->
<taskdef name="apdu" classname="com.sun.javacard.ant.tasks.APDUToolTask" classpathref="classpath" />
<taskdef name="capgen" classname="com.sun.javacard.ant.tasks.CapgenTask" classpathref="classpath" />
<taskdef name="convert" classname="com.sun.javacard.ant.tasks.ConverterTask" classpathref="classpath" />
<taskdef name="verifyexport" classname="com.sun.javacard.ant.tasks.VerifyExpTask" classpathref="classpath" />
<taskdef name="verifycap" classname="com.sun.javacard.ant.tasks.VerifyCapTask" classpathref="classpath" />
<taskdef name="verifyrevision" classname="com.sun.javacard.ant.tasks.VerifyRevTask" classpathref="classpath" />
<typedef name="appletnameaid" classname="com.sun.javacard.ant.types.AppletNameAID" classpathref="classpath" />
<typedef name="jcainputfile" classname="com.sun.javacard.ant.types.JCAInputFile" classpathref="classpath" />
<typedef name="scriptgen" classname="com.sun.javacard.ant.tasks.ScriptgenTask" classpathref="classpath" />

<target name="init">
    <mkdir dir="${target.path.classes}" />
</target>

<target name="clean">
    <delete dir="${target.path.classes}" />
</target>

<target name="compile" depends="init" description="Compile source code to class files">
    <javac debug="${javac.debug}" 
    optimize="${javac.optimize}" 
    srcdir="${source.path}" 
    destdir="${target.path.classes}"
    source="${javac.version.source}"
    target="${javac.version.target}">
    <classpath refid="classpath" />
    </javac>
</target>

<target name="convert" depends="compile" description="Convert class files to cap files">
    <convert packagename="${package.name}"
    packageaid="${package.aid}" 
    majorminorversion="${applet.version}"
    classdir="${target.path.classes}"
    outputdirectory="${target.path.cap}"
    jca="${cap.creation.jca}"
    exp="${cap.creation.exp}"
    cap="true"
    debug="${cap.creation.debug}" verbose="${cap.creation.verbose}"
    noverify="${cap.creation.noverify}">
    <appletnameaid aid="${applet.aid}" appletname="${applet.name}" />
    <exportpath refid="capexport" />
    <classpath refid="classpath" />
    </convert>
</target>

<target name="all" depends="clean, convert" />

</project>

使用的build.properties:

# Source folder
source.folder                   =   src/org/thomas

# Java Card Development Kit folders
jcdk.basefolder                 =   lib/javaCardKit303
jcdk.subfolder.apiexportfiles   =   api_export_files
jcdk.subfolder.libs             =   lib

# Target folders (will be created, no need to adapt)
target.basefolder               =   target
target.subfolder.classes        =   classes
target.subfolder.applet         =   applet

# Applet properties
package.aid     =   0x41:0x41:0x41:0x41:0x41:0x41:0x41:0x41:0x41:0x42
package.name    =   org.thomas

applet.aid      =   0x41:0x41:0x41:0x41:0x41:0x41:0x41:0x41:0x41:0x42:0x42
applet.name     =   TlvApplet
applet.version  =   1.0

# Java class compiler options
javac.debug             =   no
javac.optimize          =   no 
javac.version.source    =   1.5
javac.version.target    =   1.5


# CAP file creation options
cap.creation.verbose    =   false
cap.creation.noverify   =   false
cap.creation.debug      =   false
cap.creation.jca        =   false
cap.creation.exp        =   false

因此怀疑要使用api_connected.jar编译上限,但是从工具包中删除文件,并没有改变任何内容。

任何帮助将不胜感激。在此先感谢,托马斯

1 个答案:

答案 0 :(得分:2)

该卡根本不支持java卡API的TLV类。 JC API只是一个建议,但卡制造商可能会选择实施它的一个子集。

一般来说,javacardx中的任何内容都是可选的(因此最后是x)。但必须实现javacard中的API方法。即使对于javacard包和类,也不是所有功能都可以在运行时使用。例如,加密算法可能不存在。