JavaCard (erste Schritte): Difference between revisions

From
Jump to navigation Jump to search
No edit summary
Line 93: Line 93:
==Erstellen einer eigenen Anwendung==
==Erstellen einer eigenen Anwendung==


Das Erstellen eines Builds erfolgt mit Ant für JavaCards[https://github.com/martinpaljak/ant-javacard], dessen .jar im Projektverzeichnis platziert wird. Außerdem wird eine SDK benötigt. Hier wird die SDK Version 2.2.2 und die Java Version 8 verwendet.
TODO

===Projektdateien===

Die <code>build.xml</code> für den Ant-Task sieht dann wiefolgt aus:

<syntaxhighlight lang="xml">
<project name="JavaCardHelloWorld" basedir=".">

<taskdef name="javacard" classname="pro.javacard.ant.JavaCard" classpath="ant-javacard.jar"/>

<javacard>
<cap jckit="./sdks/jc222_kit" aid="0102030405" package="main" output="SimpleHello.cap" sources="src/main/">
<applet class="main.SimpleHello" aid="0102030405060708"/>
</cap>
</javacard>

</project>
</syntaxhighlight>

Und das HelloWorld <code>SimpleHello.java</code>:

<syntaxhighlight lang="java">
package main;

import javacard.framework.*;

public class SimpleHello extends Applet {
final static byte HELLO_CLA = (byte)0xb0;

private static final byte[] helloWorld = { 'H' };

private SimpleHello() {
register();
}

public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException {
new SimpleHello();
}

@Override
public void process(APDU apdu) throws ISOException {
byte[] buf = apdu.getBuffer();

if ((buf[ISO7816.OFFSET_CLA] == 0) && (buf[ISO7816.OFFSET_INS] == (byte)0xa4)) {
return;
}

if (buf[ISO7816.OFFSET_CLA] != HELLO_CLA) {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}

sendHelloWorld(apdu);
}

private void sendHelloWorld(APDU apdu) {
byte[] buffer = apdu.getBuffer();

short length = (short) helloWorld.length;
Util.arrayCopyNonAtomic(helloWorld, (short) 0, buffer, (short) 0, length);
apdu.setOutgoingAndSend((short) 0, length);
}
}
</syntaxhighlight>

Das Projektverzeichnis:

<pre>
.
|------ src/
| |------ main/
| |------ SimpleHello.java
|------ sdks/
| |------ jc222_kit/
|------ ant-javacard.jar
|------ gp.jar
|------ build.xml
|------ SimpleHello.cap
</pre>

===Auf die Karte bringen===

Schließlich wird für den Build die Java-Homevariable auf Version 8 gesetzt:

<pre>
export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/"
</pre>

...Der Ant-Build ausgeführt:

<pre>
ant
</pre>

...Und das Applet installiert:

<pre>
java -jar gp.jar -install SimpleHello.cap -default
</pre>

Der Aufruf mit <code>java -jar gp.jar -d -applet 0102030405060708 --apdu B0000000</code> liefert nun den Buchstaben H als Hexcode <code>0x48</code> zurück.

Revision as of 18:18, 7 October 2022

Erste Schritte: Installation einer Beispielanwendung

Hier erfolgt zunächst der erste Test der Funktionalität der SmartCard durch Installation eines Applets, das eine einfache Guthabenkarte implementiert, hier Simple Wallet[1].

Installiert und angesprochen kann die JavaCard mittels GlobalPlatformPro[2].

Installiert wird die Applikation durch:

java -jar gp.jar -install simplewallet.cap -default

Angesprochen wird die Karte durch APDU Kommandos. Vor jeder Operation wird das Simple Wallet Applet mit ihrer AID F000A0000E00 ausgewählt.

Guthaben verändern

Das Guthaben kann beispielsweise mit dem Code B040000001[AMOUNT, 1 Bytes] erhöht werden:

java -jar gp.jar -a "00A4040006F000A0000E0000" -a "B04000000105" -debug -verbose

Ausgabe:

GlobalPlatformPro v20.01.23-0-g5ad373b
Running on Linux 5.15.0-48-generic amd64, Java 17.0.4 by Private Build
# Detected readers from JNA2PCSC
[*] REINER SCT cyberJack RFID basis 00 00
SCardConnect("REINER SCT cyberJack RFID basis 00 00", T=*) -> T=1, 3B80800101
SCardBeginTransaction("REINER SCT cyberJack RFID basis 00 00")
Reader: REINER SCT cyberJack RFID basis 00 00
ATR: 3B80800101
More information about your card:
    http://smartcard-atr.appspot.com/parse?ATR=3B80800101

A>> T=1 (4+0006) 00A40400 06 F000A0000E00 00
A<< (0000+2) (33ms) 9000
A>> T=1 (4+0001) B0400000 01 05
A<< (0000+2) (25ms) 9000
A>> T=1 (4+0000) 00A40400 00 
A<< (0018+2) (19ms) 6F108408A000000151000000A5049F6501FF 9000
[TRACE] GPSession -  [6F]
[TRACE] GPSession -      [84] A000000151000000
[TRACE] GPSession -      [A5]
[TRACE] GPSession -          [9F65] FF
[DEBUG] GPSession - Auto-detected ISD: A000000151000000
SCardEndTransaction("REINER SCT cyberJack RFID basis 00 00")
SCardDisconnect("REINER SCT cyberJack RFID basis 00 00", true) tx:23/rx:24

Alternativ kann das Guthaben auch mit B030000001[AMOUNT, 1 Bytes] reduziert werden. Die Antwort 0x9000 steht hier für "Erfolgreich".

Guthaben auslesen

Das Guthaben kann dann mit dem Code B050000002 ausgelesen werden:

java -jar gp.jar -a "00A4040006F000A0000E0000" -a "B050000002" -debug -verbose

Ausgabe:

GlobalPlatformPro v20.01.23-0-g5ad373b
Running on Linux 5.15.0-48-generic amd64, Java 17.0.4 by Private Build
# Detected readers from JNA2PCSC
[*] REINER SCT cyberJack RFID basis 00 00
SCardConnect("REINER SCT cyberJack RFID basis 00 00", T=*) -> T=1, 3B80800101
SCardBeginTransaction("REINER SCT cyberJack RFID basis 00 00")
Reader: REINER SCT cyberJack RFID basis 00 00
ATR: 3B80800101
More information about your card:
    http://smartcard-atr.appspot.com/parse?ATR=3B80800101

A>> T=1 (4+0006) 00A40400 06 F000A0000E00 00
A<< (0000+2) (28ms) 9000
A>> T=1 (4+0000) B0500000 02 
A<< (0002+2) (15ms) 0005 9000
A>> T=1 (4+0000) 00A40400 00 
A<< (0018+2) (23ms) 6F108408A000000151000000A5049F6501FF 9000
[TRACE] GPSession -  [6F]
[TRACE] GPSession -      [84] A000000151000000
[TRACE] GPSession -      [A5]
[TRACE] GPSession -          [9F65] FF
[DEBUG] GPSession - Auto-detected ISD: A000000151000000
SCardEndTransaction("REINER SCT cyberJack RFID basis 00 00")
SCardDisconnect("REINER SCT cyberJack RFID basis 00 00", true) tx:22/rx:26

Das Guthaben wird hier mit 0x0005 vor dem Returncode 0x9000 (Erfolgreich) zurückgegeben.

Erstellen einer eigenen Anwendung

Das Erstellen eines Builds erfolgt mit Ant für JavaCards[3], dessen .jar im Projektverzeichnis platziert wird. Außerdem wird eine SDK benötigt. Hier wird die SDK Version 2.2.2 und die Java Version 8 verwendet.

Projektdateien

Die build.xml für den Ant-Task sieht dann wiefolgt aus:

<project name="JavaCardHelloWorld" basedir=".">

    <taskdef name="javacard" classname="pro.javacard.ant.JavaCard" classpath="ant-javacard.jar"/>

    <javacard>
        <cap jckit="./sdks/jc222_kit" aid="0102030405" package="main" output="SimpleHello.cap" sources="src/main/">
            <applet class="main.SimpleHello" aid="0102030405060708"/>
        </cap>
    </javacard>

</project>

Und das HelloWorld SimpleHello.java:

package main;

import javacard.framework.*;

public class SimpleHello extends Applet {
    final static byte HELLO_CLA = (byte)0xb0;

    private static final byte[] helloWorld = { 'H' };

    private SimpleHello() {
        register();
    }

    public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException {
        new SimpleHello();
    }

    @Override
    public void process(APDU apdu) throws ISOException {
        byte[] buf = apdu.getBuffer();

        if ((buf[ISO7816.OFFSET_CLA] == 0) && (buf[ISO7816.OFFSET_INS] == (byte)0xa4)) {
            return;
        }

        if (buf[ISO7816.OFFSET_CLA] != HELLO_CLA) {
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }

        sendHelloWorld(apdu);
    }

    private void sendHelloWorld(APDU apdu) {
        byte[] buffer = apdu.getBuffer();

        short length = (short) helloWorld.length;
        Util.arrayCopyNonAtomic(helloWorld, (short) 0, buffer, (short) 0, length);
        apdu.setOutgoingAndSend((short) 0, length);
    }
}

Das Projektverzeichnis:

.
|------	src/
|	|------	main/
|		|------	SimpleHello.java
|------	sdks/
|	|------	jc222_kit/
|------	ant-javacard.jar
|------	gp.jar
|------	build.xml
|------	SimpleHello.cap

Auf die Karte bringen

Schließlich wird für den Build die Java-Homevariable auf Version 8 gesetzt:

export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/"

...Der Ant-Build ausgeführt:

ant

...Und das Applet installiert:

java -jar gp.jar -install SimpleHello.cap -default

Der Aufruf mit java -jar gp.jar -d -applet 0102030405060708 --apdu B0000000 liefert nun den Buchstaben H als Hexcode 0x48 zurück.