JavaCard

From air
Jump to navigation Jump to search

JavaCard est un canevas d’exécution d'application pour carte à puce développé en Java.

Les APIs

Les outils

Global Platform

Global Platform est un standard permettant l'installation de cardapplets.

Carte étudiante (ancienne génération)

Présentation de la carte

Script pour lister les card applets

mode_211
gemXpressoPro
enable_trace
establish_context
card_connect
select -AID a000000018434d
open_sc -security 3 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 // Open secure channel
get_status -element 20
card_disconnect
release_context

Script pour lister les card applets sélectionnables

mode_211
gemXpressoPro
enable_trace
establish_context
card_connect
select -AID a000000018434d
open_sc -security 3 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 // Open secure channel
get_status -element 40
card_disconnect
release_context

Application Java pour lister quelques informations de la carte

package fr.imag.javacard;

import javax.smartcardio.*;
import java.util.*;

public class Main {
    static class Util {
        static final String HEXES = "0123456789ABCDEF";

        public static String getHex(byte[] raw) {
            if (raw == null) {
                return null;
            }
            final StringBuilder hex = new StringBuilder(2 * raw.length);
            for (final byte b : raw) {
                hex.append(HEXES.charAt((b & 0xF0) >> 4))
                        .append(HEXES.charAt((b & 0x0F)));
            }
            return hex.toString();
        }
    }

    private static byte[] appletAID = {0x55, 0x6E, 0x69, 0x76, 0x2E, 0x55, 0x4A, 0x46};
    private final static byte INS_SELECT = (byte) 0xA4;
    private final static byte INS_GETDATA = (byte) 0xCA;

    static class Command {
        String description;

        Command(String description) {
            this.description = description;
        }
    }

    private static final Map<Integer, Command> COMMAND_MAP =
            Collections.unmodifiableMap(new HashMap<Integer, Command>() {{
                put(1, new Command("ID(?)"));
                put(2, new Command("Version(?)"));
                put(3, new Command("(?)"));
                put(4, new Command("INE"));
                put(5, new Command("Creation(?)"));
                put(6, new Command("Update(?)"));
            }});

    public static CardTerminal selectCardTerminal() throws Exception {
        Scanner in = new Scanner(System.in);
        TerminalFactory tf = TerminalFactory.getDefault();
        List<CardTerminal> ctlist = null;
        ctlist = tf.terminals().list();
        if (ctlist.size() == 0) {
            throw new Exception("No reader present");
        }
        if (ctlist.size() == 1) {
            return ctlist.get(0);
        }

        int index = 0;
        do {

            System.out.println("Readers:");
            System.out.println("============================================");
            for (CardTerminal ct : ctlist) {
                System.out.println(index++ + ": " + ct.getName());
            }
            System.out.print("Select a reader:");
            index = in.nextInt();
        } while (index < 0 || index >= ctlist.size());

        return ctlist.get(index);
    }

    public static void selectApplication(CardChannel cc) throws Exception {
        System.out.println("Selecting \"Univ.UJF\" application");

        CommandAPDU apdu = new CommandAPDU(
                0x00, INS_SELECT,
                0x4, 0x0,
                appletAID);

        ResponseAPDU rapdu = cc.transmit(apdu);
        if (rapdu.getSW() != 0x9000) {
            throw new Exception("Can't select \"Univ.UJF\" application: "
                    + Integer.toHexString(rapdu.getSW()));
        }

    }

    public static void main(String[] args) {
        try {
            CardTerminal ct = selectCardTerminal();
            Card c = ct.connect("T=0");
            ATR atr = c.getATR();
            System.out.println("ATR : " + Util.getHex(atr.getBytes()));
            CardChannel cc = c.getBasicChannel();

            selectApplication(cc);

            for (int id : COMMAND_MAP.keySet()) {
                Command cmd = COMMAND_MAP.get(id);
                CommandAPDU apdu = new CommandAPDU(
                        0x00, INS_GETDATA,
                        (byte) id, 0x00, new byte[]{0x01});

                ResponseAPDU rapdu = cc.transmit(apdu);
                if (rapdu.getSW() != 0x9000) {
                    throw new Exception("Can't get data (" + id + "): "
                            + Integer.toHexString(rapdu.getSW()));
                }
                System.out.println(cmd.description + ":"
                        + new String(rapdu.getData()));
            }
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}

Muscle pour la carte étudiante

Compilation

(De préference sous Linux)

  • Télécharger les sources de Muscle
svn co svn://svn.debian.org/muscleplugins/trunk/MCardApplet
  • Télécharger Java Card 2.1.2 Development Kit: lien
  • Changer common.xml en modifiant:
Index: common.xml
===================================================================
--- common.xml  (revision 297)
+++ common.xml  (working copy)
@@ -62,8 +62,8 @@
                executable="${JAVA_BUILD_HOME}/bin/javac"
                srcdir="${APPLET_SRC}"
                destdir="${OUTPUT_DIR}"
-                target="${VM_TARGET_VERSION}"
-                source="${VM_SOURCE_VERSION}">
+                target="1.1"
+                source="1.2">
                 <bootclasspath>
                     <pathelement location="${BOOTCLASSPATH}"/>
                 </bootclasspath>
  • Modifier le fichier JCOP.properties
CARD_NAME=JCOP
JAVA_BUILD_HOME=PATH_VERS_JDK
JC_HOME=PATH_VERS JC212
API_JAR=${JC_HOME}/lib/api21.jar
API_EXPORT_FILES=${JC_HOME}/api21_export_files

Installation

Deplacer le fichier CardEdge.cap dans le dossier de GPShell et lancer le script suivant

mode_211
gemXpressoPro
enable_trace
establish_context
card_connect
select -AID a000000018434d
open_sc -security 3 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 // Open secure channel
install -file CardEdge.cap -sdAID A000000018434D00 -nvCodeLimit 4000
card_disconnect
release_context

Initialisation

Comme spécifié ici, l'applet à besoin d'être initialisé (par exemple avec opensc):

opensc-tool -s 00:A4:04:00:06:A0:00:00:00:01:01 \
-s B0:2A:00:00:38:08:4D:75:73:63:6C:65:30:30:04:01:08:30:30:30:30:30:30:30:30:08:30:30:30:30:30:30:30:30:05:02:08:30:30:30:30:30:30:30:30:08:30:30:30:30:30:30:30:30:00:00:17:70:00:02:01