Kartu pintar dan Kerangka OpenCard

Pengembang Java sebelumnyakolom, "Kartu pintar: Primer", memberikan gambaran umum tentang kartu pintar dan cara kerjanya. Itu termasuk bagian tentang standar kartu pintar, memperkenalkan konsep OpenCard. Seperti yang dijelaskan di artikel pertama, OpenCard adalah standar terbuka yang menyediakan interoperabilitas aplikasi kartu pintar di NCs, terminal POS, desktop, laptop, set top, dan PDA. OpenCard dapat menyediakan 100% aplikasi kartu pintar Java murni. Aplikasi kartu pintar seringkali tidak murni karena mereka berkomunikasi dengan perangkat eksternal atau menggunakan perpustakaan pada klien. Dalam artikel ini kami akan memberikan dua implementasi untuk dua pembaca kartu yang berbeda, menunjukkan bagaimana Anda akan menambahkan dukungan untuk pembaca kartu ke OpenCard. Kami berharap port untuk Litronic, Gemplus, Schlumberger, Bull, Toshiba, dan SCM akan segera tersedia, pujian dari OpenCard danJavaWorld .

pengantar

Untuk menggunakan kartu pintar, Anda harus bisa membaca kartu dan berkomunikasi dengannya menggunakan aplikasi. OpenCard menyediakan kerangka kerja untuk ini dengan mendefinisikan antarmuka yang harus diimplementasikan. Kerangka OpenCard mendefinisikan beberapa antarmuka ini. Setelah antarmuka ini diterapkan, Anda dapat menggunakan layanan lain di lapisan atas API. Misalnya, dengan pembaca yang terhubung dengan benar, OpenCard dapat memulai agen kartu Java setiap kali kartu dimasukkan. Agen kartu kemudian dapat berkomunikasi dengan aplikasi pada kartu pintar melalui terminal kartu dalam konteks sesi.

Artikel ini akan mengajari Anda cara menghubungkan terminal kartu ke OpenCard. Artikel selanjutnya akan membahas cara menulis agen. Sebuah aplikasi tes kecil, yang mendapatkan string ATR (Answer to Reset) disediakan. ATR sangat penting untuk kartu pintar. Kami akan menggunakan kit pengembangan OpenCard dan menjelaskan implementasi untuk dua pembaca kartu pintar yang berbeda menggunakan Antarmuka Terminal Kartu. Teknik yang dibahas dalam artikel untuk memperkuat pembaca, memulai sesi kartu, dan penggunaan Unit Data Protokol dan Unit Data Protokol Aplikasi dapat digunakan kembali untuk sebagian besar pembaca di pasar.

Meskipun tidak perlu menggunakan OpenCard dalam membuat 100% aplikasi kartu pintar Java murni, tanpa itu pengembang dipaksa untuk menggunakan antarmuka yang dikembangkan sendiri untuk kartu pintar. (Untuk penjelasan rinci tentang arti sebenarnya dari 100% murni, lihat bagian Sumber.) OpenCard juga menyediakan pengembang dengan antarmuka ke PC / SC (antarmuka aplikasi kartu pintar yang dikembangkan oleh Microsoft dan lainnya untuk berkomunikasi dengan kartu pintar dari berbasis Win32. platform untuk PC) untuk penggunaan perangkat yang ada pada platform Win32. Baca dan pelajari cara menggunakan kartu pintar dengan browser Anda.

Arsitektur OpenCard: Gambaran umum

OpenCard menyediakan arsitektur untuk mengembangkan aplikasi di Java yang menggunakan kartu pintar atau perangkat lain yang sesuai dengan ISO 7816 pada platform target yang berbeda seperti Windows, komputer jaringan, workstation Unix, Webtops, set top, dan sebagainya. Kerangka OpenCard menyediakan antarmuka pemrograman aplikasi (API), yang memungkinkan Anda untuk mendaftarkan kartu, mencari kartu di pembaca, dan secara opsional meminta agen Java memulai saat kartu dimasukkan ke dalam pembaca. Arsitektur OpenCard digambarkan pada Gambar 1.

Arsitektur Framework OpenCard terdiri dari CardTerminal, para CardAgent, Agen dan / atau aplikasi yang berinteraksi dengan komponen ini. OpenCard terdiri dari empat paket Java dengan awalan opencard :

  1. aplikasi
  2. io
  3. agen
  4. terminal

Paket terminal di OpenCard

Paket opencard.application dan opencard.io menyediakan API tingkat tinggi yang digunakan oleh pengembang aplikasi. Layanan yang diperlukan oleh tingkat tinggi API dilakukan oleh kelas di opencard.agent dan opencard.terminal paket. The opencard.agent paket abstrak fungsi smart card melalui CardAgent. Paket opencard.terminal mengabstraksi terminal kartu (juga dikenal sebagai pembaca kartu ). Memahami struktur paket opencard.terminal diperlukan untuk memahami contoh implementasi terminal kartu yang disediakan dalam artikel ini.

Terminal kartu mengabstraksi perangkat yang digunakan dalam sistem komputer untuk berkomunikasi dengan kartu pintar. The opencard.terminal paket berisi kelas untuk mewakili hardware kartu-terminal, untuk berinteraksi dengan pengguna, dan untuk mengelola sumber daya kartu-terminal. Tidak semua pembaca memiliki kemampuan tersebut. Saat mengimplementasikan pembaca yang tidak memiliki entri keyboard, kami akan menggunakan UserInteractionHandler.

Representasi terminal kartu

Setiap terminal kartu diwakili oleh sebuah instance kelas CardTerminalyang mendefinisikan terminal kartu abstrak yang sesuai dengan OpenCard. Terminal kartu mungkin memiliki satu atau lebih slot untuk kartu pintar dan secara opsional layar dan papan tombol atau papan PIN. Slot dari terminal kartu diwakili oleh instance kelas abstrak Slot, yang menawarkan metode untuk menunggu kartu dimasukkan, untuk berkomunikasi dengan kartu, dan mengeluarkannya (jika memungkinkan).

Interaksi pengguna

Menggunakan kartu pintar memerlukan interaksi dengan pengguna - untuk verifikasi pemegang kartu. Antarmuka UserInteractionmenyediakan fungsionalitas ini. Ini menyediakan metode untuk menulis pesan ke layar dan menerima masukan dari pengguna. Terminal kartu yang tidak mendukung semua fitur interaksi pengguna dapat menggunakan UserInteractionHandler, yang mengimplementasikan a UserInteractionsebagai antarmuka pengguna grafis berdasarkan abstract windowing toolkit (AWT).

Pengelolaan sumber daya

Pembaca kartu dan kartu memerlukan pengelolaan sumber daya sehingga agen dapat diberikan tingkat kontrol akses yang mereka butuhkan. Manajemen sumber daya menyediakan untuk berbagi terminal kartu dan kartu yang dimasukkan di dalamnya di antara agen dalam sistem. Misalnya, Anda menggunakan kartu cerdas untuk menandatangani dokumen pada saat yang sama saat pesan email prioritas tinggi masuk yang perlu diterjemahkan menggunakan kartu cerdas Anda. Manajemen sumber daya mengatur akses ke CardTerminaldan port yang benar.

Manajemen sumber daya untuk terminal kartu dicapai oleh CardTerminalRegistrykelas OpenCard. Hanya ada satu contoh CardTerminalRegistry: registri terminal kartu di seluruh sistem. Registri terminal kartu di seluruh sistem melacak terminal kartu yang dipasang di sistem. Registri terminal kartu dapat dikonfigurasi dari properti saat sistem dimulai atau secara dinamis melalui registerdan unregistermetode untuk menambah atau menghapus terminal kartu dari registri secara dinamis.

Selama registrasi terminal kartu, CardTerminalFactorydiperlukan untuk membuat instance kelas implementasi yang sesuai untuk terminal kartu. Pabrik terminal kartu menggunakan nama tipe dan tipe konektor dari terminal kartu untuk menentukan CardTerminalkelas yang akan dibuat. Konsep pabrik terminal kartu memungkinkan pabrikan terminal kartu untuk menentukan pemetaan antara nama tipe yang mudah digunakan dan nama kelas.

Contoh implementasi: terminal kartu IBM

Di bagian ini, kami akan menjelaskan integrasi terminal kartu IBM 5948 ke OpenCard. Terminal kartu IBM 5948 memiliki satu slot untuk kartu pintar, layar LCD, dan bantalan PIN. Itu terhubung ke workstation atau PC melalui port serial. Informasi lebih lanjut tentang pembaca ini tersedia di

Sumber daya

bagian.

Untuk mengakses terminal kartu dari dalam OpenCard, implementasi untuk kedua kelas abstrak CardTerminaldan Slotharus disediakan. Ini telah diberi nama IBM5948CardTerminaldan IBM5948Slot, masing-masing. Selain itu, diperlukan CardTerminalFactorynama yang sesuai IBMCardTerminalFactory. Implementasi terminal terdiri dari paket com.ibm.zurich.smartcard.terminal.ibm5948 . Gambar 2 menggambarkan hubungan pewarisan antara kelas-kelas opencard.terminal , kelas-kelas Java, dan implementasi terminal. Diagram kelas juga berisi kelas IBM5948Driver, yang tidak mengimplementasikan kelas abstrak OpenCard tetapi berfungsi sebagai antarmuka Java ke pustaka driver terminal yang ditulis dalam C.

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

Terminal kartu dikontrol dengan mengirimkan PDU kontrol ke metode data IBM5948Driver. Format PDU kontrol sesuai dengan ISO 7816-4. Hal ini memungkinkan kita untuk menyebarkan kelas opencard.agent.CommandPDUuntuk membangun PDU dan opencard.agent.ResponsePDUmenangani tanggapannya.

The IBM5948CardTerminalkelas meluas kelas CardTerminal. Konstruktor menginisialisasi kelas super dan membuat instance driver. Kemudian itu membuat instance array untuk menampung slot, dan membuat instance satu IBM5948Slotmesin virtual untuk mewakili satu-satunya slot dari terminal kartu IBM 5948.