读取 JavaCard Classic 上的 TLV 编码数据

Read TLV encoded data on JavaCard Classic

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

cap 文件创建成功,但是当我尝试将它安装到卡上时出现 gpshell 错误:

load() returns 0x80206A80 (6A80: Wrong data / Incorrect values in command data.)

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

使用的小程序代码(不使用 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

所以怀疑 cap 是用 api_connected.jar 编译的,但是从工具包中删除文件,没有任何改变。

如有任何帮助,我们将不胜感激。提前致谢,托马斯

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

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