Programmering

Smartkort og OpenCard Framework

Den forrige Java-udvikler kolonne, "Smart cards: A primer", gav et generelt overblik over smart cards og hvordan de fungerer. Det omfattede et afsnit om standardkortkort, der introducerede konceptet med OpenCard. Som beskrevet i den første artikel er OpenCard en åben standard, der giver interoperabilitet mellem chipkortapplikationer på tværs af NC'er, POS-terminaler, desktops, laptops, set tops og PDA'er. OpenCard kan levere 100% rene Java-smartcard-applikationer. Smartkortapplikationer er ofte ikke rene, fordi de kommunikerer med en ekstern enhed eller bruger biblioteker på klienten. I denne artikel vil vi give to implementeringer til to forskellige kortlæsere, der viser, hvordan du vil tilføje support til kortlæsere til OpenCard. Vi håber, at havne til Litronic, Gemplus, Schlumberger, Bull, Toshiba og SCM snart vil være tilgængelige, komplimenter af OpenCard og JavaWorld.

Introduktion

For at bruge et smartkort skal du være i stand til at læse kortet og kommunikere med det ved hjælp af en applikation. OpenCard giver en ramme for dette ved at definere grænseflader, der skal implementeres. OpenCard-rammen definerer flere af disse grænseflader. Når disse grænseflader er implementeret, kan du bruge andre tjenester i de øverste lag i API'en. For eksempel med en korrekt grænsefladeslæser kan OpenCard starte en Java-kortagent, hver gang kortet indsættes. Kortagenten kan derefter kommunikere med applikationer på smartkortet via kortterminalen i forbindelse med en session.

Denne artikel lærer dig, hvordan du tilslutter kortterminaler til OpenCard. Fremtidige artikler vil diskutere, hvordan man skriver en agent. En lille testapplikation, der får ATR (Answer to Reset) -strengen leveres. ATR er grundlæggende for smartkort. Vi tager OpenCard-udviklingssættet og forklarer implementeringer for to forskellige chipkortlæsere ved hjælp af Card Terminal Interface. De teknikker, der er diskuteret i artiklen til at tænde for læsere, starte kortsessioner og brugen af ​​protokoldataenheder og applikationsprotokoldataenheder kan genbruges for de fleste læsere på markedet.

Selvom det ikke er nødvendigt at bruge OpenCard til oprettelse af 100% rene Java-smartkortapplikationer, uden det er udviklere tvunget til at bruge hjemmevoksne grænseflader til smartkort. (For en detaljeret forklaring af, hvad 100% rent faktisk betyder, se afsnittet Ressourcer.) OpenCard giver også udviklere en grænseflade til PC / SC (en grænseflade til applikationer til chipkort udviklet af Microsoft og andre til kommunikation med smartkort fra Win32-baseret platforme til pc'er) til brug af eksisterende enheder på Win32-platforme. Læs videre, og lær, hvordan du bruger smartkort med din browser.

OpenCard-arkitektur: En oversigt

OpenCard giver en arkitektur til udvikling af applikationer i Java, der bruger smartkort eller andre ISO 7816-kompatible enheder på forskellige målplatforme såsom Windows, netværkscomputere, Unix-arbejdsstationer, Webtops, set-tops og så videre. OpenCard Framework giver en applikationsprogrammeringsgrænseflade (API), der giver dig mulighed for at registrere kort, se efter kort i læsere og eventuelt få Java-agenter til at starte, når kort indsættes i læseren. Arkitekturen af ​​OpenCard er afbildet i figur 1.

Arkitekturen i OpenCard Framework består af CardTerminal, det CardAgent, de agenter og / eller applikationer, der interagerer med disse komponenter. OpenCard består af fire Java-pakker med præfikset opencard:

  1. Ansøgning
  2. io
  3. agent
  4. terminal

Terminalpakken i OpenCard

Pakkerne opencard.application og opencard.io leverer API'en på højt niveau, der bruges af applikationsudvikleren. De tjenester, der kræves af API'en på højt niveau, udføres af klasser i opencard.agent og opencard.terminal pakker. Det opencard.agent pakke udtager funktionaliteten af ​​smartkortet gennem CardAgent. Pakke opencard.terminal uddrager kortterminalerne (også kendt som kortlæsere). Forstå strukturen af opencard.terminal pakken er påkrævet for at forstå eksempler på implementeringer af kortterminaler, der er angivet i denne artikel.

En kortterminal abstraherer den enhed, der bruges i et computersystem til at kommunikere med et chipkort. Det opencard.terminal pakken indeholder klasser, der repræsenterer kortterminalens hardware, interagerer med brugeren og administrerer kortterminalressourcer. Ikke alle læsere har disse evner. Når vi implementerer en læser, der ikke har tastaturindgang, bruger vi UserInteractionHandler.

Kortterminalrepræsentation

Hver kortterminal er repræsenteret af en forekomst af klasse CardTerminal der definerer den abstrakte OpenCard-kompatible kortterminal. En kortterminal kan have en eller flere pladser til smartkort og eventuelt et display og et tastatur eller en PIN-pad. Slots på en kortterminal er repræsenteret af forekomster af den abstrakte klasse Slot, der tilbyder metoder til at vente på, at et kort indsættes, kommunikere med kortet og skubbe det ud (hvis det er muligt).

Brugerinteraktion

Brug af et smart card kræver interaktion med brugeren - til verifikation af kortholderen. Grænsefladen Brugerinteraktion indeholder denne funktionalitet. Det giver metoder til at skrive en besked på skærmen og modtage input fra brugeren. Kortterminaler, der ikke understøtter alle brugerinteraktionsfunktioner, kan gøre brug af UserInteractionHandler, som implementerer en Brugerinteraktion som en grafisk brugergrænseflade baseret på det abstrakte vinduesværktøjssæt (AWT).

Ressourcestyring

Kort og kortlæsere kræver ressourcehåndtering, så agenter kan få det adgangskontrolniveau, de har brug for. Ressourcehåndtering sørger for deling af kortterminaler og kortene indsat i dem blandt agenterne i systemet. Sig for eksempel, at du bruger dit chipkort til at underskrive et dokument på samme tid, som der kommer en højprioritets mailbesked, der skal dekodes ved hjælp af dit smartkort. Ressourcestyring mægler adgangen til CardTerminal og den korrekte port.

Ressourcehåndteringen for kortterminaler opnås af CardTerminalRegistry klasse af OpenCard. Der er kun en forekomst af CardTerminalRegistry: det systemdækkende kortterminalregister. Det systemdækkende kortterminalregister holder styr på de kortterminaler, der er installeret i systemet. Kortterminalregistret kan konfigureres fra egenskaber ved systemstart eller dynamisk igennem Tilmeld og afregistrere metoder til dynamisk tilføjelse eller fjernelse af kortterminaler fra registreringsdatabasen.

Under registreringen af ​​en kortterminal a CardTerminalFactory er nødvendig for at oprette en forekomst af den tilsvarende implementeringsklasse til kortterminalen. Kortterminalfabrikken bruger kortterminalens typenavn og stiktype til at bestemme CardTerminal klasse at skabe. Konceptet med en kortterminalfabrik tillader en producent af kortterminaler at definere en kortlægning mellem brugervenlige typenavne og klassenavnet.

Eksempelimplementering: IBM-kortterminal

I dette afsnit beskriver vi integrationen af ​​IBM 5948-kortterminalen i OpenCard. IBM 5948-kortterminalen har en plads til smartkort, en LCD-skærm og en PIN-pad. Den er forbundet til arbejdsstationen eller pc'en via en seriel port. Flere oplysninger om denne læser findes i

Ressourcer

afsnit.

For at få adgang til en kortterminal fra OpenCard, en implementering for begge abstrakte klasser CardTerminal og Slot skal leveres. Disse er blevet navngivet IBM5948CardTerminal og IBM5948Slot, henholdsvis. Derudover en passende CardTerminalFactory som hedder IBMCardTerminalFactory er nødvendig. Terminalimplementeringen består af pakke com.ibm.zurich.smartcard.terminal.ibm5948. Figur 2 viser arveforholdet mellem klasser af opencard.terminal, Java-klasser og terminalimplementering. Klassediagrammet indeholder også klasse IBM5948Driver, som ikke implementerer nogen abstrakt klasse af OpenCard, men fungerer som en Java-grænseflade til terminaldriverbiblioteket skrevet i C.

Vi antager, at terminalen allerede er tilsluttet arbejdsstationen eller pc'en, og at den serielle port er konfigureret til at arbejde med terminalen. I det følgende afsnit beskriver vi designet og implementeringen af ​​driveren, terminalen, slotten og kortterminalfabrikken. Konfigurationen af ​​kortterminalregistret findes også.

Kortterminaldriveren

Kortterminalen leveres med en driver, der er tilgængelig som et dynamisk linkbibliotek (DLL). DLL har en C API, der tilbyder funktionerne CT_init, CT_dataog CT_close:

  • Funktionen CT_init bruges til at åbne en forbindelse til en kortterminal, der er forbundet til en bestemt seriel port. Når forbindelsen er oprettet, kan protokoldataenheder (PDU) udveksles med kortterminalen, og APU'er kan udveksles med det smartkort, der er tilsluttet terminalens slot via CT_data fungere.

  • Det CT_data opkald bruges til at sende en PDU og hente svaret fra henholdsvis terminalen eller smartkortet.

  • Det CT_close funktion bruges til at lukke forbindelsen til kortterminalen og frigøre eventuelle ressourcer.

Succes eller fiasko for alle tre API-opkald er angivet med returkoden.

Java API

I lighed med C API definerer vi en Java API til kortterminaldriveren. Java API til kortterminalen består af klasse IBM5948Driver, som har indfødte metoder, der kalder C API. Vi besluttede at implementere så meget funktionalitet som muligt i Java og har kun noget "lim" kode skrevet i C. Faktisk er parametrene for ctInit og ctLuk metode videregives lige til den respektive C API-funktion. Da arrays er organiseret forskelligt i C og Java, skal de håndteres ved opkald til Java Native Interface (JNI) API på den virtuelle maskine. De oprindelige metoder returnerer returkoden for C API. Gennemførelsen af ctData metoden er vist nedenfor:

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; usigneret trist trist = VÆRD; usigneret char dad = destination; usigneret kort responsLength = (usigneret kort) responseMax; usigneret char * commandArray; usigneret char * responsArray; jclass cls = (* env) -> GetObjectClass (env, that); jfieldID fid; jint ctn; fid = (* env) -> GetFieldID (env, cls, "ctNumber", "I"); hvis (fid == NULL) {return (CT_ERR_HTSI); } ctn = (* env) -> GetIntField (env, that, fid); commandArray = (usigneret char *) (* env) -> GetByteArrayElements (env, command, 0); responseArray = (usigneret char *) (* env) -> GetByteArrayElements (env, respons, 0); rc = CT_DATA (ctn, & dad, & sad, commandLength, commandArray, & responseLength, responseArray); (* env) -> ReleaseByteArrayElements (env, command, (underskrevet char *) commandArray, 0); (* env) -> ReleaseByteArrayElements (env, respons, (signeret char *) responseArray, 0); fid = (* env) -> GetFieldID (env, cls, "responsLength", "I"); hvis (fid == NULL) {return (CT_ERR_HTSI); } (* env) -> SetIntField (env, that, fid, responseLength); returnere rc; } 

De oprindelige metoder, der er beskrevet ovenfor, efterligner C API i Java. Årsagen til dette var at have så lidt C-kode at vedligeholde som muligt. Oven på de oprindelige metoder, som er private, er metoderne i det, dataog tæt implementeres. De kalder de oprindelige metoder og kaster en undtagelse, hvis returkoden angiver en fejl. I tilfælde af datametoden returneres responsbyte-arrayet efter en vellykket afslutning af det oprindelige metodekald. Eksemplet nedenfor viser datametoden:

synkroniseret byte [] data (byte destination, byte [] pdu) kaster CardTerminalException {int rc = ctData (destination, pdu, pdu.length, respons, respons.length); hvis (rc == CT_OK) {byte [] resultat = ny byte [responsLængde]; System.arraycopy (respons, 0, resultat, 0, responsLength); returresultat } ellers smid nyt CardTerminalException (rc2String (rc)); } 

For at holde hukommelsesstyring inde i Java tildeles et buffersvar for svaret fra terminalen en gang og sendes videre til den oprindelige kode. Da C API ikke er med, er metoderne til IBM5948Driver skal erklæres synkroniseret.

Implementering af kortterminalen

Kortterminalen styres ved at sende kontrol-PDU'er til datametoden for IBM5948Driver. Kontrol-PDU'ernes format er ISO 7816-4-kompatibelt. Dette giver os mulighed for at implementere klasse opencard.agent.CommandPDU at konstruere PDU'erne og opencard.agent.ResponsePDU til at håndtere svarene.

Det IBM5948CardTerminal klasse udvider klassen CardTerminal. Konstruktøren initialiserer superklassen og initierer føreren. Derefter instantierer det arrayet til at holde slots og instantierer en instans af IBM5948Slot til at repræsentere den eneste plads på IBM 5948-kortterminalen.