Smartcards und das OpenCard Framework

Der vorherige Java-EntwicklerDie Spalte "Smartcards: Eine Einführung" gab einen allgemeinen Überblick über Smartcards und deren Funktionsweise. Es enthielt einen Abschnitt über Smartcard-Standards, in dem das Konzept der OpenCard vorgestellt wurde. Wie im ersten Artikel beschrieben, ist OpenCard ein offener Standard, der die Interoperabilität von Smartcard-Anwendungen über NCs, POS-Terminals, Desktops, Laptops, Set-Tops und PDAs hinweg ermöglicht. OpenCard kann 100% reine Java-Smartcard-Anwendungen bereitstellen. Smartcard-Anwendungen sind häufig nicht rein, da sie mit einem externen Gerät kommunizieren oder Bibliotheken auf dem Client verwenden. In diesem Artikel werden zwei Implementierungen für zwei verschiedene Kartenleser bereitgestellt, um zu demonstrieren, wie Sie OpenCard um Unterstützung für Kartenleser erweitern können. Wir hoffen, dass bald Ports für Litronic, Gemplus, Schlumberger, Bull, Toshiba und SCM verfügbar sein werden, Komplimente von OpenCard undJavaWorld .

Einführung

Um eine Smartcard verwenden zu können, müssen Sie in der Lage sein, die Karte zu lesen und über eine Anwendung mit ihr zu kommunizieren. OpenCard bietet hierfür ein Framework, indem Schnittstellen definiert werden, die implementiert werden müssen. Das OpenCard-Framework definiert mehrere dieser Schnittstellen. Sobald diese Schnittstellen implementiert sind, können Sie andere Dienste in den oberen Schichten der API verwenden. Mit einem ordnungsgemäß angeschlossenen Lesegerät kann OpenCard beispielsweise einen Java-Kartenagenten starten, wenn die Karte eingesetzt wird. Der Kartenagent kann dann im Rahmen einer Sitzung über das Kartenterminal mit Anwendungen auf der Smartcard kommunizieren.

In diesem Artikel erfahren Sie, wie Sie Kartenterminals an OpenCard anschließen. In zukünftigen Artikeln wird erläutert, wie ein Agent geschrieben wird. Eine kleine Testanwendung, die die ATR-Zeichenfolge (Answer to Reset) erhält, wird bereitgestellt. Die ATR ist für Smartcards von grundlegender Bedeutung. Wir werden das OpenCard-Entwicklungskit nehmen und die Implementierungen für zwei verschiedene Smartcard-Lesegeräte mithilfe der Card Terminal-Schnittstelle erläutern. Die im Artikel beschriebenen Techniken zum Einschalten von Lesegeräten, zum Starten von Kartensitzungen und zur Verwendung von Protokolldateneinheiten und Anwendungsprotokolldateneinheiten können für die meisten Leser auf dem Markt wiederverwendet werden.

Während es nicht erforderlich ist, OpenCard zum Erstellen von 100% reinen Java-Smartcard-Anwendungen zu verwenden, sind Entwickler gezwungen, OpenCard für Smartcards zu verwenden. (Eine ausführliche Erklärung dessen, was 100% rein wirklich bedeutet, finden Sie im Abschnitt Ressourcen.) OpenCard bietet Entwicklern auch eine Schnittstelle zu PC / SC (eine von Microsoft und anderen entwickelte Smartcard-Anwendungsschnittstelle für die Kommunikation mit Smartcards von Win32-basiert Plattformen für PCs) zur Verwendung vorhandener Geräte auf Win32-Plattformen. Lesen Sie weiter und lernen Sie, wie Sie Smartcards mit Ihrem Browser verwenden.

OpenCard-Architektur: Ein Überblick

OpenCard bietet eine Architektur für die Entwicklung von Anwendungen in Java, die Smartcards oder andere ISO 7816-kompatible Geräte auf verschiedenen Zielplattformen wie Windows, Netzwerkcomputern, Unix-Workstations, Webtops, Set-Tops usw. verwenden. Das OpenCard Framework bietet eine Anwendungsprogrammierschnittstelle (API), mit der Sie Karten registrieren, nach Karten in Lesegeräten suchen und optional Java-Agenten starten können, wenn Karten in das Lesegerät eingelegt werden. Die Architektur von OpenCard ist in Abbildung 1 dargestellt.

Die Architektur des Opencard Framework von dem aus CardTerminal, die CardAgentdie Agenten und / oder Anwendungen , die in Wechselwirkung mit diesen Komponenten. OpenCard besteht aus vier Java-Paketen mit dem Präfix opencard :

  1. Anwendung
  2. io
  3. Agent
  4. Terminal

Das Terminalpaket in OpenCard

Die Pakete opencard.application und opencard.io stellen die vom Anwendungsentwickler verwendete allgemeine API bereit. Die von der High-Level-API benötigten Dienste werden von Klassen in den Paketen opencard.agent und opencard.terminal ausgeführt . Das Paket opencard.agent abstrahiert die Funktionalität der Smartcard über das CardAgent. Das Paket opencard.terminal abstrahiert die Kartenterminals (auch als Kartenleser bezeichnet ). Das Verständnis der Struktur des Pakets opencard.terminal ist erforderlich, um die in diesem Artikel bereitgestellten Beispielimplementierungen von Kartenterminals zu verstehen.

Ein Kartenterminal abstrahiert das Gerät, das in einem Computersystem zur Kommunikation mit einer Smartcard verwendet wird. Das Paket opencard.terminal enthält Klassen zur Darstellung der Hardware des Kartenterminals, zur Interaktion mit dem Benutzer und zur Verwaltung der Ressourcen des Kartenterminals. Nicht alle Leser haben diese Fähigkeiten. Bei der Implementierung eines Lesegeräts ohne Tastatureingabe verwenden wir das UserInteractionHandler.

Darstellung des Kartenterminals

Jedes Kartenterminal wird durch eine Klasseninstanz dargestellt CardTerminal, die das abstrakte OpenCard-kompatible Kartenterminal definiert. Ein Kartenterminal kann einen oder mehrere Steckplätze für Smartcards und optional ein Display und eine Tastatur oder ein PIN-Pad aufweisen. Die Steckplätze eines Kartenterminals werden durch Instanzen der abstrakten Klasse dargestellt Slot, die Methoden zum Warten auf das Einsetzen einer Karte, zum Kommunizieren mit der Karte und zum Auswerfen (falls möglich) bietet.

Benutzerinteraktion

Die Verwendung einer Smartcard erfordert die Interaktion mit dem Benutzer - zur Überprüfung des Karteninhabers. Die Schnittstelle UserInteractionbietet diese Funktionalität. Es bietet Methoden zum Schreiben einer Nachricht auf das Display und zum Empfangen von Eingaben vom Benutzer. Kartenterminals, die nicht alle Benutzerinteraktionsfunktionen unterstützen, können das verwenden UserInteractionHandler, das UserInteractioneine grafische Benutzeroberfläche basierend auf dem Abstract Winding Toolkit (AWT) implementiert .

Resourcenmanagement

Karten und Kartenleser erfordern eine Ressourcenverwaltung, damit den Agenten die erforderliche Zugriffskontrolle gewährt werden kann. Das Ressourcenmanagement ermöglicht die gemeinsame Nutzung von Kartenterminals und der darin eingelegten Karten zwischen den Agenten im System. Angenommen, Sie verwenden Ihre Smartcard, um ein Dokument zu signieren, während gleichzeitig eine E-Mail-Nachricht mit hoher Priorität eingeht, die mit Ihrer Smartcard dekodiert werden muss. Das Ressourcenmanagement entscheidet über den Zugriff auf den CardTerminalund den richtigen Port.

Das Ressourcenmanagement für Kartenterminals wird von der CardTerminalRegistryOpenCard-Klasse übernommen. Es gibt nur eine Instanz von CardTerminalRegistry: die systemweite Registrierung des Kartenterminals. Die systemweite Kartenterminalregistrierung verfolgt die im System installierten Kartenterminals. Die Registrierung des Kartenterminals kann anhand der Eigenschaften beim Systemstart oder dynamisch durch registerund anhand von unregisterMethoden zum dynamischen Hinzufügen oder Entfernen von Kartenterminals zur Registrierung konfiguriert werden.

Während der Registrierung eines Kartenterminals wird a CardTerminalFactorybenötigt, um eine Instanz der entsprechenden Implementierungsklasse für das Kartenterminal zu erstellen. Die Kartenterminalfabrik verwendet den Typnamen und den Steckertyp des Kartenterminals, um die CardTerminalzu erstellende Klasse zu bestimmen . Das Konzept einer Kartenterminalfabrik ermöglicht es einem Kartenterminalhersteller, eine Zuordnung zwischen benutzerfreundlichen Typnamen und dem Klassennamen zu definieren.

Beispielimplementierung: IBM Kartenterminal

In diesem Abschnitt beschreiben wir die Integration des IBM 5948-Kartenterminals in OpenCard. Das IBM 5948-Kartenterminal verfügt über einen Steckplatz für Smartcards, ein LCD-Display und ein PIN-Pad. Es ist über eine serielle Schnittstelle mit der Workstation oder dem PC verbunden. Weitere Informationen zu diesem Reader finden Sie in der

Ressourcen

Sektion.

Um einen Kartenterminal für den Zugriff von innen Opencard, eine Implementierung für beiden abstrakten Klassen CardTerminalund Slotmuß zur Verfügung gestellt werden. Diese wurden benannt IBM5948CardTerminalund IBM5948Slotsind. Zusätzlich wird ein entsprechender CardTerminalFactoryName IBMCardTerminalFactorybenötigt. Die Terminalimplementierung besteht aus dem Paket com.ibm.zurich.smartcard.terminal.ibm5948 . Abbildung 2 zeigt die Vererbungsbeziehungen zwischen den Klassen von opencard.terminal , den Java-Klassen und der Terminalimplementierung. Das Klassendiagramm enthält auch eine Klasse IBM5948Driver, die keine abstrakte Klasse von OpenCard implementiert, sondern als Java-Schnittstelle zur in C geschriebenen Terminaltreiberbibliothek dient.

We assume that the terminal is already connected to the workstation or PC, and that the serial port is configured to work with the terminal. In the following section, we describe the design and implementation of the driver, the terminal, the slot, and the card terminal factory. The configuration of the card terminal registry also is provided.

The card terminal driver

The card terminal is shipped with a driver that is available as a dynamic link library (DLL). The DLL has a C API that offers the functions CT_init, CT_data, and CT_close:

  • The function CT_init is used to open a connection to a card terminal that is connected to a certain serial port. After the connection has been established, protocol data units (PDU) can be exchanged with the card terminal and APUs can be exchanged with the smart card that is plugged into the slot of the terminal via the CT_data function.

  • The CT_data call is used to send one PDU and retrieve the response from the terminal or the smart card, respectively.

  • The CT_close function is used to close the connection to the card terminal and release any resources.

Success or failure of all three API calls is indicated by the return code.

The Java API

Similar to the C API, we define a Java API for the card terminal driver. The Java API for the card terminal consists of class IBM5948Driver, which has native methods calling the C API. We decided to implement as much functionality as possible in Java and have only some "glue" code written in C. In fact, the parameters of the ctInit and ctClose method are just passed on to the respective C API function. Since arrays are organized differently in C and Java, they need to be handled by calls to the Java Native Interface (JNI) API of the virtual machine. The native methods return the return code of the C API. The implementation of the ctData method is shown below:

JNIEXPORT jint JNICALL Java_com_ibm_zurich_smartcard_terminal_ibm5948_IBM5948Driver_ctData(JNIEnv *env, jobject that, jbyte destination, jbyteArray command, jint commandLength, jbyteArray response, jint responseMax) { short rc; unsigned char sad = HOST; unsigned char dad = destination; unsigned short responseLength = (unsigned short)responseMax; unsigned char *commandArray; unsigned char *responseArray; jclass cls = (*env)->GetObjectClass(env, that); jfieldID fid; jint ctn; fid = (*env)->GetFieldID(env, cls, "ctNumber", "I"); if(fid == NULL) { return(CT_ERR_HTSI); } ctn = (*env)->GetIntField(env, that, fid); commandArray = (unsigned char *) (*env)->GetByteArrayElements(env, command, 0); responseArray = (unsigned char *) (*env)->GetByteArrayElements(env, response, 0); rc = CT_DATA(ctn, &dad, &sad, commandLength, commandArray, &responseLength, responseArray); (*env)->ReleaseByteArrayElements(env, command, (signed char *)commandArray, 0); (*env)->ReleaseByteArrayElements(env, response, (signed char *)responseArray, 0); fid = (*env)->GetFieldID(env, cls, "responseLength", "I"); if(fid == NULL) { return(CT_ERR_HTSI); } (*env)->SetIntField(env, that, fid, responseLength); return rc; } 

The native methods described above mimic the C API in Java. The reason for this was to have as little C code to maintain as possible. On top of the native methods, which are private, the methods init, data, and close are implemented. They call the native methods and throw an exception if the return code indicates an error. In the case of the data method, the response byte array is returned upon a successful completion of the native method call. The example below shows the data method:

synchronized byte[] data(byte destination, byte[] pdu) throws CardTerminalException { int rc = ctData(destination, pdu, pdu.length, response, response.length); if (rc == CT_OK) { byte[] result = new byte[responseLength]; System.arraycopy(response, 0, result, 0, responseLength); return result; } else throw new CardTerminalException(rc2String(rc)); } 

In order to keep memory management inside Java, a buffer response for the answer from the terminal is allocated once and passed on to the native code. Since the C API is not re-entrant, the methods of IBM5948Driver must be declared synchronized.

Implementing the card terminal

Das Kartenterminal wird gesteuert, indem Steuer-PDUs an die Datenmethode des IBM5948Driver. Das Format der Steuer-PDUs ist ISO 7816-4-konform. Auf diese Weise können wir Klassen bereitstellen opencard.agent.CommandPDU, um die PDUs opencard.agent.ResponsePDUzu erstellen und die Antworten zu verarbeiten.

Die IBM5948CardTerminalKlasse erweitert die Klasse CardTerminal. Der Konstruktor initialisiert die Superklasse und instanziiert den Treiber. Anschließend wird das Array instanziiert, um die Steckplätze zu halten, und eine Instanz instanziiert IBM5948Slot, um den einzigen Steckplatz des IBM 5948-Kartenterminals darzustellen.