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 CardAgent
die Agenten und / oder Anwendungen , die in Wechselwirkung mit diesen Komponenten. OpenCard besteht aus vier Java-Paketen mit dem Präfix opencard :
- Anwendung
- io
- Agent
- 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 UserInteraction
bietet 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 UserInteraction
eine 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 CardTerminal
und den richtigen Port.
Das Ressourcenmanagement für Kartenterminals wird von der CardTerminalRegistry
OpenCard-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 register
und anhand von unregister
Methoden zum dynamischen Hinzufügen oder Entfernen von Kartenterminals zur Registrierung konfiguriert werden.
Während der Registrierung eines Kartenterminals wird a CardTerminalFactory
benö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 CardTerminal
zu 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 CardTerminal
und Slot
muß zur Verfügung gestellt werden. Diese wurden benannt IBM5948CardTerminal
und IBM5948Slot
sind. Zusätzlich wird ein entsprechender CardTerminalFactory
Name IBMCardTerminalFactory
benö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 theCT_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.ResponsePDU
zu erstellen und die Antworten zu verarbeiten.
Die IBM5948CardTerminal
Klasse 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.