Smartcards. Teil 4. JavaCard
Hallo Giktayms!Heute möchte ich über JavaCard sprechen. Dieser Artikel konzentriert sich auf das Konzept der JavaCard und einen Überblick über deren Architektur. Wenn Interesse an diesem Thema besteht, könnte ich eine separate Artikelserie schreiben, in der alle Aspekte von JavaCard ausführlich behandelt werden. Ich werde sofort sagen, dass ich Ihnen nicht beibringen werde, wie Sie Ihre erste Anwendung in JavaCard schreiben, weil Es gibt bereits zu viele Artikel im Internet darüber. Heute werden wir hauptsächlich darüber sprechen, wie JavaCard funktioniert.Eine JavaCard-basierte Smartcard ist also eine Karte, auf der Anwendungen auf der JavaCard Virtual Machine (einer eingeschränkten Version der für Smartcards angepassten Java Virtual Machine) in der sogenannten JavaCard Runtime Environment (die mit der Java Runtime Environment sehr wenig gemein hat) ausgeführt werden. .In Bezug auf die Terminologie werden Anwendungen Applets genannt und sind in Paketen enthalten. Pakete werden in CAP-Dateien verteilt (anstelle von Jar-Dateien). Pakete und Anwendungen haben eine eigene AID (Application Identifier). Dies ist erforderlich, damit sie in Befehlen wie SELECT, INSTALL, DELETE usw. eindeutig identifiziert werden können. (SELECT wird in ISO7816-4 beschrieben, und JavaCard und andere Befehle werden in der globalen Plattform beschrieben.)Der Lebenszyklus von Applets unterscheidet sich geringfügig vom üblichen Lebenszyklus von Computeranwendungen. Ein Applet ist eine beliebige Klasse, die von der Applet-Basisklasse erbt. Bei der Installation von Anwendungen wird die statische Installationsmethode aufgerufen. Diese Methode sollte ein Objekt der entsprechenden Klasse erstellen und die Registermethode darauf aufrufen. Anschließend wird das Objekt im System gespeichert und erhält eine eigene AID, die für die weitere Kommunikation mit der Anwendung verwendet wird. Das Objekt und seine Datenfelder werden im NVM (Non-Volatile Memory) gespeichert. Jedes Objekt oder Array, das von der Anwendung mit dem Operator "Neu" erstellt wurde, befindet sich ebenfalls in NVM. Dies bedeutet, dass im Gegensatz zu herkömmlichen Computerprogrammen der Status von JavaCard-Anwendungen konstant ist und auch beim Ausschalten der Karte nicht verloren geht.Kommunikation mit der Anwendung
Jeder offene logische Kanal hat zu jeder Zeit eine aktive Anwendung. Eine aktive Anwendung empfängt alle vom Terminal gesendeten APDUs. Wenn eine APDU empfangen wird, ruft die JavaCard die Prozessmethode der aktiven Anwendung auf, die die empfangene APDU als einzigen Parameter verwendet. Diese Methode ist der Kern des Applets, da sie Anforderungen vom Terminal verarbeitet. Die resultierende APDU wird auch zum Senden von Antworten verwendet.Ein Applet kann auf zwei Arten aktiviert werden:- Beim Zurücksetzen der Karte oder beim Öffnen eines logischen Kanals aktiviert das System normalerweise die Anwendung, die als Standardanwendung markiert ist
- Verwenden des Befehls SELECT mit P1 = 0x04 und der AID (vollständig oder teilweise) der Anwendung in Data
Wenn die Anwendung mit dem Befehl SELECT aktiviert wird, wird unmittelbar nach der Aktivierung die Prozessmethode mit der APDU aufgerufen, die diesen Befehl enthält. Somit kann das Applet bei Aktivierung Informationen als Antwort auf einen SELECT-Befehl senden. Die Applet-Klasse stellt die Methode selectedApplet () bereit, um festzustellen, ob der empfangene Befehl die Aktivierung der Anwendung verursacht hat.Die Anwendung hat auch die Möglichkeit, die Methoden select () und deselect () neu zu schreiben, um sie während der Aktivierung zu initialisieren bzw. während der Deaktivierung zu de-initialisieren. Diese Methoden werden unabhängig davon aufgerufen, wie die Anwendung aktiviert wurde.Logische Kanäle können mit dem Befehl MANAGE CHANNEL geöffnet und geschlossen werden. Über offene logische Kanäle können Sie beliebige Befehle senden, einschließlich SELECT. Es sind SELECT und MANAGE CHANNEL, die die einzigen Befehle sind, die direkt vom System und nicht von der aktiven Anwendung verarbeitet werden. Obwohl im Fall des Befehls SELECT gesagt werden kann, dass er sowohl vom System als auch von der aktiven Anwendung verarbeitet wird.Die vollständigen Regeln zum Aufrufen der Anwendung und zum Verarbeiten des Befehls SELECT sind recht komplex und es gibt kaum Widersprüche zwischen der JavaCard und der globalen Plattform. Ich werde dieses Thema jedoch in einem meiner nächsten Artikel behandeln. Nun ist es erwähnenswert, dass Karten häufig den in der globalen Plattform beschriebenen Regeln folgen.Speicherverwaltung
Wie oben erwähnt, werden Objekte und Arrays standardmäßig in NVM gespeichert. Neben NVM ermöglicht JavaCard auch das Erstellen von Arrays im RAM mit einer Reihe von Methoden aus der JCSystem-Klasse. Es gibt zwei Arten von temporärem Speicher: Löschen beim Zurücksetzen und Löschen beim Abwählen. Die erste wird gelöscht, wenn die Karte ausgeschaltet oder zurückgesetzt wird. Die zweite wird gelöscht, wenn das Applet nicht mehr aktiv ist (d. H. Wenn Sie eine andere Anwendung auswählen, herunterfahren, zurücksetzen usw.). Es sollte beachtet werden, dass, obwohl der Inhalt des Arrays gelöscht wird (d. H. Alle Nullen oder Falschen werden dort geschrieben), das Array selbst verbleibt und es beispielsweise im Objektdatenfeld gespeichert werden kann.Was wird in NVM gespeichert:- Alle Objekte und ihre Datenfelder.
- Alle Arrays.
- Der Inhalt der vom neuen Operator erstellten Arrays.
Was ist im RAM gespeichert (CLEAR_ON_RESET oder CLEAR_ON_DESELECT):- , JCSystem.makeTransient<>Array. , , , JCSystem.makeTransientObjectArray(), NVM. RAM.
- Global Arrays: (APDU Install Parameters ), Global Arrays, JCSystem.makeGlobalArray().
- . .
Eine Anwendung sollte in der Regel alle Objekte und Arrays erstellen, die sie während der Installation benötigt, und nicht dynamisch. Der Grund dafür sind hauptsächlich zwei Faktoren:1) Der Wunsch, sicherzustellen, dass die Anwendung nach erfolgreicher Installation nicht nicht mehr funktioniert, wenn eine andere Anwendung den gesamten freien Speicher belegt.2) Garbage Collector - eine optionale (wenn auch sehr häufige) Funktion. Dies bedeutet, dass beim dynamischen Erstellen von Objekten das Risiko besteht, dass die erstellten Objekte niemals gelöscht werden. Dies wird im Laufe der Zeit zu einem Mangel an freiem Speicher führen. Selbst wenn es einen Garbage Collector gibt, erfolgt diese Prozedur nicht automatisch, sondern auf Anforderung der Anwendung (JCSystem.requestObjectDeletion ()).In der Folge wird Anwendungscode in Bezug auf die objektorientierte Programmierung selten „sauber“ erhalten. Die Verwendung von Common Byte [] für viele verschiedene Operationen ist eine sehr verbreitete Praxis. Klassen, die ausschließlich aus statischen Methoden bestehen und auf Byte [] ausgeführt werden, sind ebenfalls keine Seltenheit. Außerdem wird die Erstellung von Klassen und Objekten minimiert. Wenig Speicher und es muss um jeden Preis geschützt werden.Es ist auch erwähnenswert, welche Rolle das APDU-Objekt spielt. Der im RAM befindliche Puffer wird vor dem Empfang jedes Befehls gelöscht. Es ist üblich, es nicht nur als Antwort zu verwenden, sondern oft sogar als temporären Puffer. Die Größe beträgt mindestens 256 Byte oder viel mehr, wenn die Karte Extended Length unterstützt.Applet-Firewall
Ein wichtiges Merkmal von JavaCard, das Programmierer verwirren kann, ist das Vorhandensein der sogenannten Applet-Firewall. Das Ziel der Firewall ist es, zu verhindern, dass ein Applet auf die Daten eines anderen zugreifen kann. Ich muss sofort sagen, dass JavaCard die Kommunikation zwischen Anwendungen über gemeinsam nutzbare Schnittstellen ermöglicht und dass Pakete Bibliotheken von Klassen und Funktionen sind, die in verschiedenen Anwendungen verwendet werden können. Aus diesem Grund ist eine Firewall erforderlich. Die Grundprinzipien der Applet-Firewall lauten wie folgt:- Jede Anwendung gehört zu einem Kontext. Alle Anwendungen aus demselben Paket gehören zum selben Kontext.
- Jedes Objekt gehört zu einer Anwendung oder einem System.
- Ein Paket ohne Anwendungen (Bibliothek) hat keinen Kontext. Objekte aus seinen Klassen gehören zu der Anwendung, die sie erstellt hat.
- Es gibt immer einen aktiven Kontext im System.
- (/ ) , .
- .
- . . , , firewall.
- CLEAR_ON_DESELECT , .
Über die gemeinsam nutzbare Schnittstelle kann ein Programmierer zulassen, dass bestimmte Methoden eines Objekts für Anwendungen aus einem anderen Kontext verfügbar sind. Wenn eine dieser Methoden aufgerufen wird, wechselt das System den Kontext zu dem Kontext, zu dem das Objekt gehört, das die gemeinsam nutzbare Schnittstelle bereitstellt. Dies bedeutet, dass diese Methode nur auf Objekte zugreifen kann, die zu ihrem Kontext gehören. Wenn Sie beispielsweise dieses Methodenbyte [] als Parameter aus dem ursprünglichen Kontext übergeben, tritt beim Zugriff ein Fehler auf. Nach Abschluss der Methodenausführung wechselt der Kontext zurück zum ursprünglichen.Die Anwendung hat auch Zugriff auf bestimmte Objekte, die zum System gehören. Solche Objekte werden als Einstiegspunkte bezeichnet. Es gibt zwei Arten von Einstiegspunkten: temporär und permanent. Permanente Einstiegspunkte sind einfach, der Zugriff auf sie ist aus jedem Kontext möglich. Ein Beispiel hierfür sind Objekte aus der AID-Klasse. Temporäre Einstiegspunkte haben andererseits eine Einschränkung, die verhindert, dass sie in den Datenfeldern des Objekts oder in den statischen Feldern der Klasse gespeichert werden. Ein Beispiel für einen temporären Einstiegspunkt ist ein APDU-Objekt.Ab JavaCard 3.0.4 können auch globale Arrays mit der Methode JCSystem.makeGlobalArray () erstellt werden. Ihr Verhalten entspricht genau dem von temporären Einstiegspunkten. Sie werden hauptsächlich als Parameter für Methoden benötigt, die mit der Shareable Interface-Technik aufgerufen werden.Atomarität und Transaktionen
JavaCard garantiert atomare Operationen beim Ändern von Datenfeldern von Objekten oder Klassen. Die Atomizität wird auch durch Methoden bereitgestellt, die an Arrays arbeiten (mit Ausnahme derjenigen, deren Name das Suffix NonAtomic enthält). Dies bedeutet, dass beispielsweise Util.arrayCopy entweder alle Bytes kopiert (falls erfolgreich) oder das Array im Falle eines Fehlers oder Energieverlusts unverändert lässt.Wenn Sie mehrere konstante Felder und Arrays in einer atomaren Operation ändern müssen, bietet JavaCard auch die Funktion JCSystem.beginTransaction () zum Starten der Transaktion und JCSystem.commitTransaction () zum Abschließen. Alle Änderungen, die in Arrays und konstanten Feldern zwischen Aufrufen von JCSystem.beginTransaction () und JCSystem.commitTransaction () auftreten, werden automatisch Teil der Transaktion. Wenn die Transaktion aufgrund eines Fehlers, eines Energieverlusts oder eines Aufrufs der JCSystem.abortTransaction () -Methode abgebrochen wird, stellt das System den ursprünglichen Zustand wieder her. Es sei daran erinnert, dass die technische Implementierung der Transaktion einen zusätzlichen Systempuffer verwendet. Wenn der Puffer voll ist, gibt das System einen TransactionException-Fehler aus.Rmi
JavaCard unterstützt die RMI-Technologie (Remote Metod Invocation). In diesem Artikel werde ich diese Technologie nicht widmen. Ich kann nur sagen, dass diese Funktionalität nicht üblich ist und viele Karten sie nicht unterstützen.API
Der größte Teil der JavaCard-API ist der Kryptografie gewidmet. Es gibt Klassen zum Verschlüsseln, Erstellen und Überprüfen einer digitalen Signatur, zum Generieren von Schlüsseln und Zufallszahlen, zum Berechnen von Prüfsummen und Hashes sowie zum Implementieren von Schlüsselaustauschschemata. Neben der Kryptografie bietet JavaCard auch Klassen zum Speichern und Überprüfen von PINs und sogar biometrischen Daten. Die übrigen Klassen bieten Zugriff auf die in anderen Kapiteln beschriebenen Funktionen oder sind Hilfsprogramme für die Arbeit mit Zeichenfolgen, Zahlen, TLV usw. Die API wird in einer anderen Artikelserie interpretiert.Wichtige JavaCard-Einschränkungen im Vergleich zu Java
Die Programmiersprache der JavaCard-Anwendung ist Java. Fast Java. Daher werden die Typen char, float, double, long und enum nicht unterstützt. Der int-Typ ist für Karten optional (normalerweise unterstützen ihn moderne Karten) und seine Verwendung führt, wenn er nicht durch die entsprechende Option aktiviert wird, zu einem Fehler beim Konvertieren der Anwendung in eine CAP-Datei. Vergessen Sie für, Iterator und Lambda. Generika, statischer Import und Anmerkungen (nur Runtime Invisible) werden vom Konverter seit Version 3.0.0 als unterstützt Sie haben keinen Einfluss auf die Codeausführung.Zum Kompilieren des Codes wird ein gewöhnlicher JDK-Compiler verwendet. Inkompatibilitätsfehler treten nur bei der Konvertierung in eine CAP-Datei oder bei Verwendung der Smart IDE für JavaCard auf.Das größte Problem für Programmierer ist in der Tat das Fehlen eines int standardmäßig. Normalerweise werden sie wirklich nicht benötigt, daher möchte ich sie nicht unnötig aktivieren. Der Java-Compiler hat jedoch die Angewohnheit, das Ergebnis aller arithmetischen Operationen automatisch in int umzuwandeln. Um dies zu vermeiden, müssen Sie einen expliziten Typ verwenden, der im Code auf kurz oder byte umgestellt wird, wodurch der Code weniger lesbar wird.Eine weitere Einschränkung besteht bei der Initialisierung statischer Felder darin, dass sie nur mit Konstanten und Arrays initialisiert werden können, die Konstanten enthalten, nicht jedoch mit Objekten.Fazit
Das war also meine Einführung in JavaCard. Wenn Sie diesen Artikel interessant finden oder zumindest Ihr Interesse an diesem Thema geweckt haben, können Sie in den Kommentaren schreiben, worüber Sie konkret mehr wissen möchten. So kann ich entscheiden, in welcher Reihenfolge und in wie vielen Details über eine bestimmte Funktionalität und Anwendung von JavaCard geschrieben werden soll. In jedem Fall wird der nächste Artikel der Global Platform diese Reihe abschließen. Source: https://habr.com/ru/post/de380543/
All Articles