Die Aufgabe der im Folgenden beschriebenen OSCI-OSCI-Bibliothek besteht darin, Anwendungsprogrammen und Fachverfahren eine Softwarekomponente zur Verfügung zu stellen, mit deren Hilfe sie das OSCI-Transportprotokoll zum Erzeugen und Empfangen von Nachrichten gemäß der OSCI-Transport-1.2-Spezifikation nutzen können. Die OSCI-Bibliothek soll eine möglichst einfache Integration von OSCI 1.2 in bestehende Systeme ermöglichen. Im Zusammenwirken mit den später noch näher zu erläuternden externen Modulen umfasst sie alle für Benutzer im Sinne der Spezifikation erforderlichen Funktionalitäten, nämlich Aufbau, Versand, Empfang, Speicherung, Ver- und Entschlüsselung sowie die mathematische Signaturprüfung sämtlicher Nachrichtentypen. Mit Blick auf die Fachverfahrensintegration bildet die Schnittstelle der OSCI-OSCI-Bibliothek den Zugang zu einer kompletten OSCI-Infrastruktur und ist somit der einzige Punkt, an dem eine Anpassung an die unterschiedlichen Fachverfahren erfolgen muss.
Das vorliegende Dokument setzt Kenntnisse der OSCI-Spezifikation 1.2 sowie der Begleitdokumentation zur OSCI-Spezifikation "Entwurfsprinzipien, Sicherheitsziele und -mechanismen" voraus. Die in der OSCI-1.2-Spezifikation erwähnten Literaturhinweise gelten ebenfalls für dieses Dokument. Besonders hervorzuheben sind hier die SOAP-Spezifikation, die Spezifikation für SOAP mit Attachment, die XML-Signature-Spezifikation sowie die XML-Encryption-Spezifikation.
Weitere wichtige Voraussetzungen zum Verständnis des vorliegenden Dokuments sind Kenntnisse in der Programmiersprache JAVA sowie ein Überblick über die von SUN zur Verfügung gestellte Kryptographieschnittstelle JCA/JCE. Die vorliegende Dokumentation bezieht sich auf die Implementierung in der Programmiersprache JAVA.
Im folgenden Kapitel wird der Leistungsumfang der OSCI-Bibliothek geschildert. Nach der Interpretation der OSCI-Spezifikation folgen eine Beschreibung der Schnittstellen zu externen Modulen, Beschreibungen der Programmierschnittstelle, der Fehlerbehandlung sowie des grundsätzlichen Aufbaus der Bibliothek. Abschließend werden anhand mehrerer Use-Cases die Abläufe für verschiedene Nachrichtentypen dargestellt.
Die zentrale Aufgabe der OSCI-Bibliothek besteht in der Komposition valider OSCI-Nachrichten für den Versand, sowie der Dekomposition von OSCI-Nachrichten bei deren Empfang und der Prüfung ihrer syntaktischen Korrektheit. Weiter werden alle kryptografischen Funktionen zur Signaturerzeugung und -prüfung sowie Ver- und Entschlüsselung über Funktionen der Bibliothek verwaltet, wobei die eigentliche Abarbeitung kryptografischer Aufgaben inkl. der Zugriffe auf Krypto-Token durch entsprechende Drittimplementierungen zur Verfügung gestellt werden müssen.
In diesem Sinne werden durch die OSCI-Bibliothek alle für den vollständigen Aufbau einer OSCI-Nachricht benötigten Objekte wie die eigentlichen Inhaltsdaten, die Signatur- und Verschlüsselungszertifikate aller Kommunikationsbeteiligten und deren physikalische Adressen in Form entsprechender Klassen bzw. deren Attribute bereitgestellt.
Die Erstellung und Weiterverarbeitung von Inhaltsdaten ist nicht Aufgabe der OSCI-Bibliothek, sondern muss durch die Client-Systeme und Fachanwendungen erfolgen. Durch die Klassen und Methoden der Bibliothek wird lediglich sichergestellt, dass diese Schema-konform in die Nachrichtenobjekte eingebettet werden.
Eine weitere wesentliche Aufgabe der OSCI-Bibliothek besteht in der Steuerung und Überwachung des Kommunikationsvorgangs. Für diesen Zweck stellt die Bibliothek Klassen und Methoden zur Verfügung, anhand derer die Plausibilität einer Kommunikation überprüft und dokumentiert werden kann.
Methoden für den technischen Versand und Empfang von OSCI-Nachrichten (z.B. auf Basis des HTTP-Protokolls), die Bereitstellung kryptografischer Funktionen für die Signatur und Verschlüsselung von Nachrichten sowie die Visualisierung signierter Nachrichtenkomponenten sind nicht Bestandteil der OSCI-Bibliothek. Diese Funktionalitäten müssen durch separate Module realisiert und durch JAVA-Interfaces der OSCI-Bibliothek eingebunden werden. Dies erlaubt den Einsatz unterschiedlicher Module für den jeweiligen Aufgabenbereich.
Außerhalb des Funktionsumfangs und der Kontrolle der Bibliothek liegt die TrustViewerService-Implementierung zur sicheren Visualisierung der zu signierenden Inhaltsdaten.
OSCI Transport 1.2 lässt beliebig viele Inhaltsdatencontainer zu. Die Bibliothek stellt die Funktionalitäten zur Verfügung, mit denen diese Inhaltsdatencontainer konform zur OSCI-Spezifikation aufgebaut werden können.
Die vorliegende Implementierung wurde für eine JAVA-Laufzeitumgebung der Version 1.4 entwickelt. Die Bibliothek selbst greift nicht auf plattformspezifischen (native) Code zu und ist daher auf allen Systemen einsetzbar, für die eine solche Laufzeitumgebung verfügbar ist.
Bei dem Design der OSCI-Bibliothek wurde versucht, größtmöglichen Komfort für den Benutzer zu erreichen ohne ihn in seinen Möglichkeiten einzuschränken. Die Grenzen der OSCI-Bibliothek sollen im nächsten Schaubild dargestellt werden.
Weitere Details zu den Grenzen der OSCI-Bibliothek werden im Kapitel 4 beschrieben.
Die OSCI-Spezifikation definiert XML-Schemata, mit denen die Struktur der übertragenen Nachrichten festgelegt wird. Die OSCI-Spezifikation schreibt die Struktur der verschlüsselten und/oder signierten Inhaltsdaten vor. Die folgende Abbildung stellt die Vorgaben der OSCI-Spezifikation dar.
Die Spezifikation macht aber in einigen Punkten keine konkreten, detaillierten Angaben darüber, wie die Inhaltsdaten mit diesen Schemata behandelt werden sollen. Dies betrifft u.a. die Behandlung von verschlüsselten Daten und Attachments. Hieraus ergibt sich hinsichtlich der Verwendung der Schemata ein gewisser Interpretationsspielraum, für den in Abprache mit der OSCI-Leitstelle bei der Realisierung der OSCI-Bibliothek folgende Einschränkungen bzw. Konkretisierungen vorgenommen wurden:
Unterhalb eines ContentPackage-Elementes befinden sich lediglich ContentContainer- oder verschlüsselte ContentContainer-Elemente, die in EncryptedData-Elementen enthalten sind.
Inhaltsdaten werden grundsätzlich in Content-Elementen untergebracht, die wiederum Unterelemente von ContentContainer-Elementen sind. Content-Elemente können statt Inhaltsdaten auch ein href-Attribut enthalten, welches die Referenz auf ein der Nachricht hinzugefügtes Attachment enthält. Ein solcher Eintrag hat z.B. folgende Form:
<osci:Content Id="content1" href="cid:d:/xplog.txt"/>
Die Bibliothek stellt für Content- und ContentContainer-Elemente gleichnamige Klassen zur Verfügung, mit denen entsprechende Objekte angelegt werden können. Die ContentContainer-Klasse bietet eine Methode für das Hinzufügen von Content-Objekten.
EncryptedData-Elemente enthalten grundsätzlich nur ContentContainer- oder wiederum EncryptedData-Elemente (bei Mehrfachverschlüsselung). Die Bibliothek enthält eine entsprechende EncryptedData-Klasse, deren Konstruktor ein ContentContainer-Objekt übergeben werden kann. Enthält ein zu verschlüsselnder ContentContainer ein Content-Element mit einer Attachmentreferenz, so wird dem ContentContainer beim Verschlüsseln automatisch ein EncryptedData-Element hinzugefügt, welches die Verschlüsselungsinformationen für das Attachment enthält.
Die Signaturen von Inhaltsdaten werden gemäß OSCI-Schema in den ContentContainer neben den zu signierenden Content- oder EncryptedData-Elementen eingesetzt. Die OSCI-Bibliothek signiert grundsätzlich alle in dem ContentContainer enthaltenen Elemente, außerdem ggf. in Content-Elementen referenzierte Attachments.
Für den Einsatz der OSCI-OSCI-Bibliothek ist die Kombination mit externen Modulen erforderlich. Die Schnittstellen zu diesen Modulen gewährleisten sowohl Freiheit beim Einsatz neuer Technologien (z.B. bezüglich der krytografischen Funktionen) als auch die Möglichkeit, die OSCI-OSCI-Bibliothek an die vorhandene Infrastruktur (z.B. Datenbanken) anzubinden.
In der Abbildung 3 sind die Interfaces und Klassen dargestellt.
Die OSCI-Bibliothek übernimmt den Aufbau und das Parsen der OSCI-Dokumente. Hierzu gehört insbesondere das Anbringen der Signaturen und die Ver- bzw. Entschlüsselung.
Die OSCI-Bibliothek muss zur Erfüllung ihrer Aufgaben folgende Operationen durchführen, für die kryptographische Algorithmen erforderlich sind:
Erzeugung und Prüfung von Signaturen
Ver- und Entschlüsselung von Daten
Erzeugung von Challenge-/Responsewerten und Message-IDs
Erzeugung von kryptografischen Schlüsseln bzw. Schlüsselpaaren
Anwender der Bibliothek sollen ihre bereits vorhandenen Security-Module möglichst weiterverwenden können. Neben der Einbindung eigener Implementierungen der benötigten Algorithmen steht die Verwendung unterschiedlichster Schlüssel- und Zertifikatsressourcen im Vordergrund. Darüber hinaus muss die Verwendung von Crypto-Tokens ermöglicht werden, die neben der Bereitstellung von Schlüsseln und Zertifikaten auch die kryptographischen Operationen selbst durchführen (PKCS#11-Module, SmartCards etc.).
Im JAVA-Umfeld hat sich für die Durchführung kryptographischer Funktionen der Einsatz von JCA/JCE bewährt. Die JCA/JCE-Schnittstellen erlauben es dem Nutzer, eigene Service-Provider zu schreiben und zu registrieren, so dass hier kein neues Interface definiert werden musste, sondern auf ein bewährtes Konzept zurückgegriffen werden konnte.
Im Rahmen der OSCI-Spezifikation sind die folgenden Algorithmen vorgeschrieben worden. Außerdem wird eine Methode zur sicheren Erzeugung von Zufallszahlen benötigt.
Verschlüsselung
RSA
TDES
AES-128/192/256
Signatur (Hashen)
RIPMED-160
SHA-1
Die JAVA-Sicherheitsarchitektur stellt mit der JCA/JCE-Architektur bereits Schnittstellen, sogenannte Service Provider Interfaces zur Verfügung, die die Anbindung unterschiedlicher Implementierungen ermöglichen. Für die Bibliothek sind dabei die Interfaces
javax.crypto.CipherSpi
java.security.MessageDigestSpi
java.security.SecureRandomSpi
javax.crypto.KeyGeneratorSpi
Für die Anbindung von Crypto-Tokens wurden zwei abstrakte Klassen für die sicherheitsrelevanten Funktionen Entschlüsseln und Signieren vorgesehen:
de.osci.osci12.common.Decrypter
de.osci.osci12.common.Signer
Eine Implementierung der Signer-Klasse muss zwei Methoden enthalten, getCertificate() und sign(byte[] hash). Erstere muss das Signaturzertifikat des signierenden Rollenobjekts zurückgeben, die zweite die Signatur eines Byte-Arrays durchführen und das Ergebnis ebenfalls als Byte-Array zurückgeben.
Eine Implementierung der Decrypter-Klasse muss ebenfalls zwei Methoden enthalten, getCertificate() und decrypt(byte[] data). Erstere muss das Verschlüsselungszertifikat des verschlüsselnden Rollenobjekts zurückgeben, die zweite die Verschlüsselung eines Byte-Arrays durchführen und das Ergebnis ebenfalls als Byte-Array zurückgeben.
Das Transport-Interface ist für die Übermittlung einer fertiggestellten OSCI-Nachricht an den Empfänger vorgesehen. Das Transport-Interface ist daher unentbehrlich für die OSCI-Bibliothek und muss auf jeden Fall implementiert werden.
Die OSCI-Bibliothek stellt die Funktionalität zum Aufbau einer vollständigen OSCI-Nachricht bereit, nicht jedoch zu deren Übermittlung.
Je nach konkretem Einsatzszenario können für die Übermittlung der Nachricht unterschiedliche Protokolle zum Einsatz kommen; möglich sind z.B. http, https, ftp, smtp/pop oder jms. Alle genannten Protokolle sollten sich auf Grundlage des bereitgestellten Interfaces umsetzen lassen. Dies führte zu der Entscheidung, keinerlei protokollspezifische Eigenheiten in der Bibliothek zu berücksichtigen.
Im Prinzip hätte für den Transport der Nachricht kein Interface definiert werden müssen. Die Alternative wäre gewesen, dass die OSCI-Bibliothek eine Methode für das Auslesen der fertig aufgebauten Nachricht bereitstellt und den Transport damit vollständig in die Anwendungsschicht verlagert. Eine empfangene Nachricht würde dann einfach von der Anwendung wieder in die Bibliothek eingestellt.
Die Entscheidung, an dieser Stelle dennoch ein Interface zu definieren und den Transport somit enger mit der Bibliothek zu verzahnen, wurde primär mit dem Ziel der einfachen Austauschbarkeit der Transportkomponente getroffen. Um diese Anforderung zu erfüllen, sollte die Konfiguration der Transportkomponente über Konfigurationsdateien möglich sein und nicht aus der Anwendung heraus erfolgen.
Die Verwendung eines Interface bewirkt, dass die Bibliothek die Kontrolle erst wieder an die Applikation abgibt, nachdem die Antwortnachricht komplett aufgebaut ist. Dadurch kann die Bibliothek sogleich die Korrektheit des Dialogs (des Challenge/Response-Paares) überprüfen und eventuelle Fehler weiterreichen. Diesen Zusammenhang müsste andernfalls die Applikation herstellen.
Ein weiterer Vorteil für die Steuerung des Transports durch die Bibliothek besteht in der dadurch möglichen Optimierung des Speicherbedarfs dieser Komponente.
Das Transport-Interface wird der Bibliothek durch den Konstruktor des DialogHandlers bekannt gegeben und kann während eines Dialoges nicht gewechselt werden.
Implementierungen des Interface haben lediglich die Aufgabe, den reinen Transport der Nachricht vom Sender zum Empfänger zu realisieren. Insbesondere muss sich diese Schicht nicht um den Aufbau der SOAP-Strukturen kümmern, da diese Bestandteil der OSCI-Spezifikation sind. Das bedeutet auch, dass Fehler auf SOAP-Ebene auf beiden Seiten von der Bibliothek behandelt werden. Eine solche Fehlernachricht ist für die Transportschicht damit eine Nachricht wie jede andere.
Da die Art und Weise, wie die Zieladresse einer Nachricht aufgebaut ist, stark vom Protokoll abhängt, wird diese sehr allgemein als URI formuliert. Eine URI kann in JAVA einfach in eine URL umgewandelt werden.
Nicht zum Interface gehört z.B. eine Methode für das Setzen eines Timeout-Werts. Dieser Wert muss abhängig vom Anwendungsszenario oder sogar in Abhängigkeit der konkreten Installationsumgebung festgelegt werden und gehört daher zur Anwendungslogik. Um die Austauschbarkeit der Transportkomponente trotzdem gewährleisten zu können, sollten diese Werte mittels Konfigurationsparametern und nicht direkt aus der Anwendungslogik heraus festgelegt werden.
Je nach Verbindungstyp muss sich der User unter Umständen authentifizieren. Auch diese Aufgaben wurden in die Transportschicht ausgelagert, da sie protokollspezifisch sind.
Packagename . de.osci.osci12.extinterfaces.transport
public String getVersion()
Liefert die Versionsnummer.
public String getVendor()
Sollte den Namen des Herstellers zurückgeben.
public InputStream getResponseStream()
Liefert den Response Stream.
public boolean isOnline(URI uri)
Diese Methode wird zur Online-Überprüfung vor jedem DialogInit oder bei einem impleziten Dialog direkt vor dem sendMsg jeder Nachricht aufgerufen.
public long getContentLength()
Liefert die Länge des Response Streams.
public TransportI newInstance()
Erzeugt eine neue Instanz von der Transportschicht.
public OutputStream getConnection(URI uri, long length)
Liefert eine konkrete Connection zum Versenden eines Streams. Die Methode konnektet zu der übergebenen URI und liefert als Ergebnis einen Output-Stream in den die Bibliothek dann die OSCI-Nachricht serialisiert.
Eine detailiertere Beschreibung dieser Methoden finden sich in der JavaDoc-Dokumentation.
Folgende Schritte werden von der Bibliothek beim Versenden ausgeführt:
Die Bibliothek holt eine Instanz des Transport-Interface (newInstance()).
Mit der Methode isOnline(...) wird die Erreichbarkeit der URI überprüft.
Die Bibliothek holt von der Transport-Implementierung über die Methode 'getConnection(...)' einen Output-Stream.
Die Bibliothek schreibt die OSCI-Nachricht in den Output-Stream.
Nach dem Versenden holt sich die Bibliothek den Response-Input-Stream zur Nachricht durch die Methode (getResponseStream()).
Die Progress-Schnittstelle wird von der Bibliothek für die Anzeige von Statusmeldungen benutzt. Diese Schnittstelle wird im Zusammenhang mit zeitaufwändigen Aktionen benutzt, z.B. bei der Übermittlung von Nachrichten über die Transportschicht, beim Ver- und Entschlüsseln sowie beim Parsen von OSCI-Nachrichten. Auch bei Sequenzen von Abläufen kann die Bibliothek durch die Progress-Schnittstelle mitteilen, welcher Bearbeitungsschritt gerade durchgeführt wird.
Die OSCI-Bibliothek kommuniziert über die Progress-Schnittstelle ihre Statusmeldungen an die Anwendung. Da die Bibliothek kein eigenes GUI besitzt, muss für die Anzeige von Statusinformationen der Bibliothek ein Interface implementiert werden.
Die grafische Darstellung von Fortschritt-Statusereignissen ist ebenfalls applikationsabhängig. Auch in diesem Fall ist daher ein Interface notwendig, welches genau diese Informationen der Applikation mitteilt. Die Progress-Schnittstelle wird also benutzt, um prozentualen Fortschritt anzuzeigen oder um mitzuteilen, was gerade von der Bibliothek durchgeführt wird.
Die Schnittstelle liegt in Form eines JAVA-Interface vor. Die Registriertung der Progress-Implementierung erfolgt durch die Methode setProgressEventHandler(ProgressEventHandlerI progressEventHandler) im Dialog-Handler. Die Registrierung einer Implementierung ist optional.
Packagename. de.osci.osci12.extinterfaces.progress
public String getVersion()
Liefert die Versionsnummer.
public String getVendor()
Sollte den Namen des Herstellers zurückgeben.
public String getDescription()
Liefert eine Beschreibung zur aktuellen Implementierung.
public void event(int type, String param, int percent)
Wird aufgerufen, sobald zeitaufwendige Vorgänge in der Bibliothek der Applikation mitgeteilt werden sollen.
Eine detailliertere Beschreibung dieser Methoden finden sich in der JavaDoc-Dokumentation.
Für die OSCI-Bibliothek ist ausschließlich die Methode event(int type, String param, int percent) von Bedeutung. Diese wird von der Bibliothek bei Fortschritt-Statusereignissen aufgerufen.
Die Language-Schnittstelle dient zur Übersetzung der Fehler-, Warnung- und Progresscodes in die jeweilige Landessprache. Die Sprachen Deutsch und Englisch sind schon Bestandteil der OSCI-Bibliothek, weitere Sprachen können bei Bedarf durch die Nutzung von Resource-Dateien hinzugefügt werden.
Die OSCI-Bibliothek liefert zu jeder Meldung einen Code, der durch die Übersetzungstabellen der Resource-Language-Dateien dann sogleich den Meldungstext in der gewünschten Landessprache referenziert.
Die Language-Schnittstelle ist kein JAVA-Interface im eigentlichen Sinne, vielmehr stellt sie eine JAVA-Resource-Datei dar. Für jede Sprache ist eine Datei zu erstellen, die in folgendes Verzeichnis eingefügt werden muss: de/osci/osci12/extinterfaces/language.
Der Dateiname besteht aus dem String "Text_", dem angehängten zweistelligen Sprachkürzel nach ISO-639 und der Erweiterung ".properties". Die deutsche Sprachdatei heißt somit "Text_de.properties". Sollte die gewünschte Landessprache nicht vorhanden sein, wird auf die englischsprachige Datei zurückgegriffen
Die Bibliothek verwendet die gemäß Ländereinstellung des Systems passende Resource-Datei und kommuniziert alle Anfragen in der entsprechende Landessprache.
Die folgenden Meldungstexte stammen aus der deutschen Resorce-Datei "Text_de.properties". Es wird erkennbar, dass mit wenig Aufwand auch andere Landessprachen unterstützt werden können.
9000 = Interner Fehler beim Supplier.
9100 = Empfangene Nachricht stellt keine gültige OSCI-Nachricht dar.
9200 = Supplier verfügt nicht über den privaten Schlüssel zum Chiffrierzertifikat auf Nachrichtenebene.
9201 = Chiffrierzertifikat auf Nachrichtenebene ist widerrufen.
9202 = Auftragsdaten konnten nicht entschlüsselt werden.
9300 = Auftragsdaten stellen keinen gültigen Auftrag dar.
9400 = ConversationId oder SequenceNumber oder Response nicht korrekt.
9500 = Chiffrierzertifikat des Clients ist nicht in den Auftragsdaten enthalten.
9501 = Signatur über das Chiffrierzertifikat des Clients ist fehlerhaft.
9502 = Chiffrierzertifikat des Clients ist widerrufen.
9503 = Interner Fehler des Suppliers beim Ermitteln oder Prüfen des Chiffrierzertifikats.
3500 = Chiffrierzertifikat des Clients ist zeitlich ungültig.
3501 = Prüfung des Chiffrierzertifikats des Clients konnte nicht vollständig durchgeführt werden.
3700 = Signierzertifikat des Clients ist zeitlich ungültig.
3701 = Signierzertifikat eines Autors ist zeitlich ungültig.
3702 = Signatur über das Signierzertifikat eines Autors ist fehlerhaft.
3703 = Signierzertifikat eines Autors ist widerrufen.
3704 = Chiffrierzertifikat eines Autors ist zeitlich ungültig.
3705 = Chiffrierzertifikat des Empfängers ist zeitlich ungültig.
3707 = Zertifikatsprüfung konnte nicht vollständig durchgeführt werden.
3800 = Es liegen weitere Zustellungen für diesen Client vor.
3801 = Zu den im Auftrag angegebenen Kriterien liegen weitere Laufzettel vor.
3802 = Signatur des Empfängers über die Annahme- bzw. Bearbeitungsantwort fehlt.
0800 = Auftrag ausgeführt, Dialog beendet
0801 = Auftrag ausgeführt, Dialog weiterhin geöffnet
9600 = Auftrag ist nicht signiert, obwohl dieser Supplier für diesen Auftragstyp eine Signatur verlangt.
9601 = Signatur über Auftrag ist fehlerhaf.
9602 = Es sind nicht alle geforderten Elemente des Auftrags signiert.
9603 = Interner Fehler des Suppliers beim Prüfen der Signatur.
9700 = Signatur über das Signierzertifikat des Clients ist fehlerhaft.
9701 = Signierzertifikat des Clients ist widerrufen
9704 = Signatur über das Chiffrierzertifikat eines Autors ist fehlerhaft.
9705 = Chiffrierzertifikat eines Autors ist widerrufen.
9706 = Signatur über das Chiffrierzertifikat des Empfängers ist fehlerhaft.
9707 = Chiffrierzertifikat des Empfängers ist widerrufen.
3706 = Chiffrierzertifikat eines Lesers ist zeitlich ungültig.
9708 = Signatur über das Chiffrierzertifikat eines Lesers ist fehlerhaft.
9709 = Chiffrierzertifikat eines Lesers ist widerrufen.
9710 = Interner Fehler des Suppliers bei der Zertifikatsprüfung.
9800 = Annahme der Zustellung ohne MessageId verweigert.
9801 = Illegale MessageId (MessageId wurde nicht von diesem Supplier erzeugt oder MessageId wurde schon einmal verwendet).
9802 = Auftrag nicht innerhalb eines expliziten Dialogs gesendet, obwohl dies für diesen Auftragstyp gefordert ist.
9803 = Zu den im Auftrag angegebenen Kriterien ist keine Zustellung vorhanden.
9804 = Zu den im Auftrag angegebenen Kriterien ist kein Laufzettel vorhanden.
9805 = Empfänger hat Zustellung des Senders nicht angenommen.
9806 = Empfänger hat Zustellung des Senders angenommen, seine Auftragsantwort enthält aber keine Zustellung an den Sender.
9807 = Signatur des Empfängers über die Annahme- bzw. Bearbeitungsantwort fehlerhaft.
no_cipher_cert_intermed = Kein Verschlüsselungszertifikat für den Rollenobjekt eingestellt.
no_decrypter_intermed = Kein Decrypter-Objekt für den Intermediär eingestellt.
no_signature_cert_intermed = Kein Signaturzertifikat für den Rollenobjekt eingestellt.
no_signer_intermed = Kein Signer-Objekt für den Intermediär eingestellt.
Zum Überprüfen eines Dialogs muss man bei der OSCI-Bibliothek den aktuellen Dialog mit dem Vorgängerdialog vergleichen. Sollten bei einem Client mehrere Verbindungen aufgebaut werden oder handelt es sich um ein passives Backend, müssen somit mehrere Dialoge verwaltet werden können. Der Dialogfinder dient also zum Auffinden genau dieser schon vorhandenen Dialoge. Eine Standardimplementierung liegt der OSCI-Bibliothek bei.
Soll ein Supplier synchron Nachrichten beantworten können, muss es möglich sein, dass dieser mit mehreren Clients gleichzeitig kommuniziert. Für diesen Fall muss die OSCI-Bibliothek die Applikation nach einem schon vorhandenen Dialog fragen können, so dass die Sequenz des Dialogs nachvollzogen werden kann. Bei einem Client, der in der Regel nur einen DialogHandler hat, tritt dieses Problem nicht auf. Bei Bedarf kann die schon bestehende Implementierung des DialogFinder ersetzt und an die lokalen Anforderungen angepasst werden. Vorstellbar wären hier EJB oder Datenbankimplementierungen. Als Default-Implementierung wird eine einfache Klasse geliefert, welche die Dialog-Informationen im Speicher vorhält.
Die Standardimplementierung wird in den meisten Fällen ausreichen, um die Dialoge auch bei parallel ablaufenden OSCI-Nachrichten aufrecht zu halten. Die Möglichkeit zur Registrierung eines eigenen DialogFinder kann aber sinnvoll sein, falls die Informationen nicht nur im Hauptspeicher, sondern auch in Datenbanken persistent abgelegt werden sollen. Besonders beim Intermediär werden sehr viele Verbindungen gehalten werden müssen und mögliche Rollback-Mechanismen sollten vorgesehen werden können, diese Funktionalitäten sind im DefaultDialogFinder nicht integriert. Auch im Sinne von Loadbalancing muss es Möglichkeiten geben, Dialoge auch außerhalb des Speichers zu verwalten. Um Erweiterungen für diese Aufgabenstellungen zuzulassen, kann ein eigens entwickelter DialogFinder bei dem DialogHandler registriert werden.
Im Normalfall ist der Default-DialogFinder registriert. Soll ein individueller DialogFinder registriert werden, muss dieses beim DialogHandler geschehen. Der DialogHandler stellt die statische Methode setDialogFinder(de.osci.osci12.common.DialogFinder newDialogFinder)zur Verfügung, welche das Setzen eines eigenen DialogFinders zulässt.
package. de.osci.osci12.common
public String getVersion()
Liefert die Versionsnummer.
public String getVendor()
Sollte den Namen des Herstellers zurückgeben.
public String getDescription()
Liefert eine Beschreibung zur aktuellen Implementierung.
public DialogHandler findDialog(ControlBlockH controlBlock)
Liefert einen Dialog passend zu dem übergebenen Control-Block; sollte kein Dialog gefunden werden wird 'null' zurückgegeben.
public void addDialog(DialogHandler dialog)
Übergibt der Klasse einen Dialog für die Auswertung in der Zufunft.
public void removeDialog(DialogHandler dialog)
Entfernt einen Dialog aus der Liste der vorhandenen Dialoge. Diese Methode wird z.B nach einem Dialog-Ende aufgerufen.
Eine detailiertere Beschreibung dieser Methoden finden sich in der JavaDoc-Dokumentation.
Beim Parsen einer OSCI-Nachricht wird nach dem Lesen des Control-Block die Konsistenz des Dialogs geprüft. Hierfür wird der Dialogfinder aufgerufen und der Control-Block als Parameter übergeben. Sollte ein entsprechender Dialog existieren, wird das DialogHandler-Objekt des Control-Block zurückgegeben. Die OSCI-Bibliothek überprüft die Richtigkeit des Dialogs, aktualisiert die Parameter und führt das Parsen der Nachricht fort.
Die Datenspeicher-Schnittstelle dient zur Anbindung beliebiger Speichersysteme, etwa Datenbanken oder Dateisysteme. Diese Schnittstelle wird von der OSCI-Bibliothek genutzt, z.B. für die temporäre Zwischenspeicherung eingelesener Daten vor der Erzeugung der Signatur oder empfangener Daten vor der Entschlüsselung. Außerdem dient sie zur Speicherung empfangener, unverarbeiteter (ungeparster) Nachrichten im "Rohzustand" zum Zwecke der Archivierung. Eine Standardimplementierung liegt der OSCI-Bibliothek bei.
Nachrichten können - von Ausnahmen wie z.B. InitDialog-Nachrichten abgesehen - in der Regel nicht in einem zeitlich zusammenhängenden Vorgang verarbeitet werden. Beispielsweise findet die Ver- oder Entschlüsselung von Inhaltsdaten als Teil einer Nachricht häufig später als der unmittelbare Versand oder Empfang der Nachricht statt. Ähnliches gilt für die Erzeugung oder Prüfung von Signaturen. Aus diesem Grund muss die Bibliothek an verschiedenen Stellen des Verarbeitungsprozesses temporäre Kopien von Nachrichten (oder Teilen davon) anlegen. Um den Betrieb der OSCI-Bibliothek in unterschiedlichen Umgebungen zu gewährleisten, wurde die DataSource-Schnittstelle definiert.
Die Schnittstelle liegt in Form der abstrakten Klasse "de.osci.osci12.common.OSCIDataSource" vor. Implementierungen dieser Klasse können an zwei Punkten der OSCI-Bibliothek registriert werden:
in der Klasse de.osci.osci12.common.DialogHandler mit Hilfe der statischen Methode setDataBuffer(OSCIDataSource buffer)
in bestimmten Subklassen von de.osci.osci12.messagetypes.OSCIMessage mit Hilfe der Methode setInputDataSourceImpl(OSCIDataSource data). Betroffen sind die Klassen, die Nachrichtentypen repräsentieren, welche von Benutzern empfangen werden und die entweder Inhaltsdaten enthalten oder für den Nachweis einer Kommunikation wichtig sein können. Namentlich sind dies die Nachrichtentypen Annahmeauftrag und Bearbeitungsauftrag sowie Zustellungsantwort, Zustellungsabholantwort, Abwicklungsantwort und Weiterleitungsantwort.
Während die im DialogHandler-Objekt registrierte Implementierung von der Bibliothek für die temporäre Datenspeicherung während der Verarbeitung genutzt wird, dienen die in OSCIMessage-Objekten registrierten Implementierungen der Archivierung eingehender Nachrichten. Im DialogHandler-Objekt ist die Implementierung de.osci.osci12.common.SwapBuffer voreingestellt. Dieses Objekt schreibt die zu speichernden Daten bis zu einer konfigurierbaren Anzahl von Bytes in den Arbeitsspeicher. Die statische Variable maxBufferSize wird beim Laden der Klasse auf 1% des zu diesem Zeitpunkt verfügbaren freien Arbeitsspeichers initialisiert. Werden mehr Bytes gespeichert, wird der gesamte Datensatz in eine temporäre Datei geschrieben.
In OSCIMessage-Subklassen werden standardmäßig keine OSCIDataSource-Objekte registriert; in diesem Fall werden die eingehenden Nachrichten nicht gespeichert. Registriert eine Anwendung hier ein OSCIDataSource-Objekt, so schreibt die OSCI-Bibliothek die Nachrichten in serialisierter Form in dessen OutputStream-Objekt (s.u.). Die empfangenen Daten werden dabei unverändert byteweise in den Stream geschrieben. Die Identifikation der abgespeicherten Daten, z.B. durch Zuordnung der MessageID als Primärschlüssel in einer Datenbank oder als Dateiname, liegt in der Verantwortung der Anwendung.
package. de.osci.osci12.common
Die Klasse OSCIDataSource definiert sechs Methoden:
public abstract OSCIDataSource newInstance():
Muss eine neue Instanz des OSCIDataSource-Objekts zurückgeben.
public abstract java.io.OutputStream getOutpuStream():
Muss ein OutputStream-Objekt zurückgeben, in welches die OSCI-Bibliothek die zu speichernden Daten schreiben kann.
public abstract java.io.InputStream getInputStream():
Muss ein java.io.InputStream-Objekt zurückgeben, aus dem die gespeicherten Daten gelesen werden können. Der erste Aufruf dieser Methode muss den Schreibvorgang beenden, indem der mit getOutputStream() gelieferte Stream geschlossen wird. Außerdem muss der zurückgegebene InputStream die reset()-Methode so implementieren, dass nach deren Aufruf der Lesevorgang beim ersten Byte des gespeicherten Datensatzes fortgesetzt wird.
public abstract long getLength():
Diese Methode muss die Anzahl der gespeicherten Bytes liefern.
public String getVersion()
Liefert die Versionsnummer.
public String getVendor()
Sollte den Namen des Herstellers zurückgeben.
Eine detailiertere Beschreibung dieser Methoden finden sich in der JavaDoc-Dokumentation.
Muss die Bibliothek beim Verarbeiten, Versand oder Empfang einer Nachricht Daten abspeichern, so ruft sie zunächst die Methode newInstance() des für diesen Zweck registrierten OSCIDataSource-Objekts auf, um eine Instanz dieses Objekts zu erhalten. Anschließend werden die Daten in den von getOuputStream() gelieferten Stream geschrieben. Falls die OSCI-Bibliothek die abgespeicherten Daten im weiteren Verlauf wieder benötigt, werden sie aus dem von getInputStream() gelieferten Stream gelesen. Die Methode getLength() wird an verschiedenen Stellen, z.B. beim Aufbau von MIME-Headern, benötigt.
Im folgenden Abschnitt werden die Klassen, Interfaces und Resource-Dateien behandelt, die Anwendungsprogrammierer für den Betrieb der OSCI-Bibliothek benötigen.
Die Akteure gemäß dem Rollenmodell der OSCI-Spezifikation werden in folgenden Objekten gehalten:
Intermed (beschreibt einen Intermediär)
Originator (beschreibt einen Sender)
Addressee (beschreibt einen Empfänger)
Author (beschreibt einen Autor)
Reader (beschreibt einen Leser)
Die Rollen in einer OSCI-Sitzung ändern sich in den meisten Fällen nicht, sodass die Konstruktoren aller Rollen nahezu gleich aussehen. Eine Ausnahme bildet das Reader-Objekt, weil die OSCI-Spezifikation das Element SignatureCertificateOtherReader nicht verwendet und damit Signaturen des Reader (Rückantworten) nicht benötigt werden.
Es gibt zwei Möglichkeiten zum Aufbau der Rollen-Objekte:
Als Besitzer der privaten Schlüssel: Hier wird dem Konstruktor zum Signieren ein Signer-Objekt bzw. zum Entschlüsseln von Rückantworten ein Decrypter-Objekt übergeben. Beide Parameter können unter Umständen NULL sein. Bei einem NULL-Parameter wird keine Signatur bzw. Entschlüsselung gewünscht. Beispiel: Originator(Signer signer, Decrypter decrypter)
Als Besitzer der öffentlichen Schlüssel: Hier wird dem Konstruktor ein X509-Signaturzertifikat zur Signaturprüfung bzw. ein X509-Chiffrierzertifikat zur Verschlüsselung übergeben. Beide Parameter können unter Umständen NULL sein. Bei einem NULL-Parameter wird keine Signaturprüfung bzw. Verschlüsselung gewünscht. Beispiel: Addressee(X509Certificate signatureCertificate, X509Certificate cipherCertificate)
Der Begriff des Dialogs betrifft die Auftragsebene von OSCI-Transport. Auftrag-Antwort-Paare werden zu Dialogen zusammengefasst. Jeder Dialog umfasst mindestens ein Auftrag-Antwort-Paar. Ein Dialog besteht zwischen genau einem Client und einem Supplier. Dialoge sind in der OSCI-Spezifikation von elementarer Bedeutung. Zum Beispiel muss vor dem Abholen von Nachrichten ein Dialog eröffnet werden, um die Berechtigung hierfür zu erlangen. Die Verwaltung der Dialoginformationen über mehrere OSCI-Nachrichten hinweg übernimmt der Dialog-Handler der OSCI-Bibliothek.
Die OSCI-Bibliothek verwaltet für den Nutzer auch die Dialoge, das heißt, es wird die Richtigkeit des Tripels aus ConversationID, Sequenz-Nummer und Supplier betrachtet, sowie die Richtigkeit der Challenge- und Responsewerte.
Folgende Aufgaben übernimmte der Dialog-Handler zur Dialogverwaltung:
Verwaltung der OSCI-Sicherheitsmechanismen zur Absicherung des Dialogs. Dazu dienen Methoden zur Einstellung und zum Check von
Challenge-Response
Sequence-Number und Conversation-ID der Nachricht
Festlegung konkreter Einstellungen für das jeweilige Request/Response-Tupel (bzw. auch die gesamte Session) wie
Attribut checkSignatures-Signaturen der empfangenen Nachrichten prüfen (optional für einen Client)
Zusätzlich zu den Dialog-relevanten Informationen wird der Dialog-Handler auch als Konfigurationsinstrument benutzt. Jeder OSCI-Nachricht muss im Konstruktor ein Dialog-Handler übergeben werden, sodass statische Informationen, die sich während einer Sitzung nicht ändern, ebenfalls im Dialog-Handler mitgeführt werden.
Folgende Konfigurationsinformationen werden im Dialog-Handler verwaltet:
Konfiguration der Schnittstellen-Implementierung:
Transport
DialogFinder
Progress Event Handler
DataSource
Somit werden die meisten Schnittstellen im Dialog-Handler definiert.
Weiter werden hier die Referenzen auf folgende Akteur-Objekte einer OSCI-Kommunikation gehalten:
Originator (Sender der Nachricht, Client)
Intermediär (Supplier)
Diese Informationen werden zusammen mit der Transportschicht im Konstruktor des Dialog-Handler übergeben.
Informationen über Transportverschlüsselung, Signatur und Spracheinstellung (DesiredLanguages-Element)
Jede OSCI Request/Response-Folge erhält die Referenz auf die Dialog-Handler-Instanz, um im konkreten OSCI-Request die entsprechenden aktuellen Attributwerte setzen und die korrespondierenden Werte des jeweiligen Response auf Korrektheit gemäß OSCI-Spezifikation prüfen zu können. Nach erfolgreicher Prüfung werden die Attribute zur Dialogabsicherung jeweils sofort auf die Werte gesetzt, die für die nächste Request-Response-Sequenz gefordert sind.
Für die Initiierung einer neuen Dialogabfolge können die Attributwerte mit resetControlBlock() neu initialisiert werden.
In dem folgendem Schaubild werden die vom Dialog-Handler verwalteten Objekte dargestellt.
Die OSCI-Kommunikation verläuft generell in Form von Request/Response- Szenarien. Die OSCI-1.2-Spezifikation definiert insgesamt 20 verschiedene Nachrichtentypen, nämlich 10 Auftrags- und die dazugehörigen 10 Antwortnachrichten.
Für jeden Nachrichtentyp stellt die OSCI-Bibliothek eine repräsentierende Klasse bereit. Diese Klassen befinden sich in dem Package de.osci.osci12.messagetypes. Die gemeinsame Superklasse aller Auftragsnachrichten ist die Klasse de.osci.osci12.messagetypes.OSCIRequest, die der Antwortnachrichten de.osci.osci12.messagetypes.OSCIResponseTo. Diese beiden Klassen sind wiederum von der Klasse de.osci.osci12.messagetypes.OSCIMessage abgeleitet.
Entsprechend den in der OSCI-Spezifikation den Benutzern zugewiesenen Aufgaben müssen Anwendungen OSCI-Nachrichten erzeugen können. Sie werden vom Benutzer erstellt und vom Intermediär geparst:
Tabelle 1. Nachrichtentypen (Erstellen) und ihre zugehörigen JAVA-Klassen
Nachricht | Quellcodedateiname |
---|---|
Dialogintialisierungsauftrag | InitDialog.java |
Dialogendeauftrag | ExitDialog.java |
MessageID-Anforderungsauftrag | GetMessageId.java |
Zustellungsauftrag | StoreDelivery.java |
Zustellungsabholauftrag | FetchDelivery.java |
Laufzettelabholauftrag | FetchProcessCard.java |
Weiterleitungsauftrag | ForwardDelivery.java |
Annahmeantwort | ResponseToAcceptDelivery.java |
Abwicklungsauftrag | MediateDelivery.java |
Bearbeitungsantwort | ResponseToProcessDelivery.java |
Diese Klassen besitzen öffentliche Konstruktoren und können über setX()-Methoden mit den erforderlichen Informationen bestückt werden. Weiterhin bieten die folgenden Klassen die Möglichkeit, Inhaltsdaten in die Nachricht aufzunehmen:
Zustellungsauftrag
Weiterleitungsauftrag
Annahmeantwort
Abwicklungsauftrag
addEncryptedData(de.osci.osci12.messageparts.EncryptedData encData)
addContentContainer(ContentContainer container)
Mit Ausnahme der beiden Antwortnachrichten ResponseToAcceptDelivery und ResponseToProcessDelivery besitzen alle Klassen außerdem eine öffentliche send()-Methode, mit der der Versand der Nachricht veranlasst wird. Die Methode gibt als Rückgabeparameter ein korrespondierendes Antwortnachricht-Objekt zurück.
Die verbleibenden Nachrichtentypen werden von Anwendungen nur als Ergebnis der send-Methoden zurückgegeben (diese Nachrichtentypen werden nur vom Intermediär erstellt) oder, im Falle der beiden Auftragsnachrichten ResponseToAcceptDelivery und ResponseToProcessDelivery, von der statischen Methode parseStream(InputStream in) des IncomingMSGParser (passiver Empfänger) erstellt. Die Klassen haben daher keine öffentlichen Konstruktoren. Zur Auswertung der Nachrichten stehen in den Klassen entsprechende getX(...)-Methoden, wie z.B. getFeedback(), bereit.
Folgende OSCI-Nachrichten werden vom Intermediär erstellt und vom Client geparst:
Tabelle 2. Nachrichtentypen (Parsen) und ihre zugehörigen JAVA-Klassen
Nachricht | Quellcodedateiname |
---|---|
Dialogintialisierungsantwort | ResponseToInitDialog.java |
Dialogendeantwort | ResponseToExitDialog.java |
MessageID-Anforderungsantwort | ResponseToGetMessageId.java |
Zustellungsantwort | ResponseToStoreDelivery.java |
Zustellungsabholantwort | ResponseToFetchDelivery.java |
Laufzettelabholauftrag | ResponseToFetchProcessCard.java |
Weiterleitungsantwort | ResponseToForwardDelivery.java |
Annahmeauftrag | AcceptDelivery.java |
Abwicklungsantwort | ResponseToMediateDelivery.java |
Bearbeitungsauftrag | ProcessDelivery.java |
Eingehende Bescheibungen der Methoden der speziellen OSCI-Nachrichten-Klassen finden sich im Anhang.
Bei folgenden OSCI-Nachrichtentypen müssen nach dem Empfang die Inhaltsdaten ausgewertet werden:
Zustellungsabholantwort
Annahmeauftrag
Abwicklungsantwort
Bearbeitungsauftrag
Zum Auswerten dieser Inhaltsdaten können die ContentContainer entweder mit der Methode getContentContainer() direkt aus der Nachricht gelesen oder zuvor entschlüsselt werden. Zum Entschlüsseln eines EncryptedData-Objekts sind folgende Schritte notwendig:
Analyse des verschlüsselten Datencontainers durch die Methode getReaders(); durch diese Methode werden die Leser dieses Datencontainers bekannt gegeben.
Auf Grundlage des EncryptedData-Objekts wird die Methode decrypt(Role addressee) aufgerufen. Als Parameter muss ein Role-Objekt übergeben werden, welches einen Decrypter enthält.
Als Ergebnis gibt die Methode decrypt(Role addressee) ein MessagePart-Objekt zurück. Dieses muss noch Typ-überprüft werden. Mögliche Return-Typen sind hier Attachment, ContentContainer und EncryptedData.
Auswerten des MessageParts entsprechend der jeweiligen getX()-Methoden der Klassen von Attachment, ContentContainer und EncryptedData.
dem folgendem Schaubild wird beispielhaft die Struktur der OSCI-Nachrichtenobjekte in der OSCI-Bibliothek dargestellt.
OSCI-Nachrichten, die zur Übermittlung von Inhaltsdaten (in Form von XML-Data oder unstrukturiert als Binär-Daten) benutzt werden, enthalten immer ContentContainer zur Aufnahme dieser Informationen.
Ein ContentContainer beinhaltet Content-Elemente (und ggf. EncryptedData-Elemente), die wiederum die auftragsspezifischen Inhaltsdaten aufnehmen. Auf der Empfängerseite werden die Inhaltsdaten eines ContentContainers ausgewertet. OSCI stellt ein sicheres Übermittlungsprotokoll dar, mit dem sich Inhaltsdaten in beliebiger Form (insbesondere XML-Inhaltsdaten) nachprüfbar übertragen lassen. Das Ergebnis dieser Übertragung besteht dann in der Auswertung eben dieser Inhaltsdaten im ContentContainer sowie der Signaturen.
ContentContainer sind also Einheiten, die nur als Ganzes signiert und/oder verschlüsselt werden können. Einer OSCI-Nachricht können beliebig viele dieser ContentContainer übergeben werden. Somit kann es leicht vorkommen, dass Teile (nämlich einzelne ContentContainer) einer Nachricht unverschlüsselte Informationen enthalten, während gleichzeitig andere ContentContainer derselben Nachricht schutzwürdige Inhalte aufnehmen und deswegen signiert und/oder verschlüsselt sind.
Zum leicheren Verständnis sollen einige weitere Bibliotheks-Klassen vorgestellt werden:
Content-Objekte enthalten entweder XML-Inhaltsdaten oder eine Referenz auf ein Attachment. Alle wichtigen Informationen werden schon mit dem Konstruktor gesetzt. Das Content-Objekt stellt keine Methoden zum Signieren (diese befinden sich auf ContentContainer-Ebene) oder zum Verschlüsseln (siehe EncryptedData-Klasse) bereit. Inhaltsdaten, seien es nun XML-Daten oder Binär-Daten, werden immer erst einmal einem Content hinzugefügt. Ggf. mehrere Content-Objekte bilden Container zum Bündeln von Inhaltsdaten. Erst auf der ContentContainer-Ebene kann die Signatur bzw. Verschlüsselung erfolgen. Die Content-Klasse stellt folgende Konstruktoren zur Verfügung:
Content(Attachment attachment)
Content(java.io.InputStream ins)
Content(String data)
Die ContentContainer-Klasse stellt einen OSCI-Auftragscontainer dar. Ein ContentContainer kann einen oder mehrere Content- (XML-Datencontainer) oder EncryptedData-Objekte enthalten. Attachments werden als Content-Objekte eingestellt, die eine Referenz auf das Attachment enthalten. Daten, die in gleicher Weise zu behandeln sind (Signieren und/oder Verschlüsseln), werden zu einem ContentContainer zusammengeführt. Sobald Inhaltsdaten unterschiedlich signert und/oder verschlüsselt werden sollen, müssen diese auf verschiedene ContentContainer verteilt werden; die Übertragung erfolgt zusammen in einer OSCI-Nachricht.
Die Methoden zum Bearbeiten von Content-Objekten:
public Content[] getContents()
Liefert die enthaltenen Content-Objekte zurück.
public void addContent(Content content)
Fügt ein Content-Objekt hinzu.
public void removeContent(Content content, boolean removeAttachment)
Entfernt ein Content-Objekt.
Die Methoden zum Bearbeiten von EncryptedData-Objekten:
public EncryptedDataOSCI[] getEncryptedData()
Liefert die enthaltenen EncryptedData-Objekte.
addEncryptedData(EncryptedDataOSCI encryptedDataElement)
Fügt ein EncryptedData-Objekt hinzu.
public void removeEncryptedData(EncryptedDataOSCI encryptedDataElement, boolean removeAttachment)
Entfernt ein EncryptedData-Objekt.
Für das Signieren eines kompletten ContentContainers steht folgende Methode zu Verfügung:
public void sign(Role role, String signatureAlgorithm)
Diese Methode übernimmt das Signieren des kompletten ContentContainers einschließlich in Content-Elementen referenzierter Attachments. Für Mehrfachsignaturen kann diese Methode mehrfach mit verschiedenen Rollen-Objekten aufgerufen werden.
Die Methoden zum Auswerten des ContentContainers:
public Role[] getRoles()
Liefert alle beteiligten Rollen-Objekte (Verschlüsselung und Signatur).
public Role[] getSigners()
Liefert alle beteiligten Signatur-Rollen-Objekte.
In folgendem Beispiel werden dem ContentContainer zwei Content-Objekte mit XML-Inhaltsdaten hinzugefügt.
In folgendem Beispiel werden ein Content-Objekt mit XML-Inhaltsdaten und ein Content-Objekt mit einem Attachment als Inhalt dem ContentContainer hinzugefügt.
Die EncryptedData-Klasse wird benutzt, um XML-Encryption-Elemente zu erzeugen, d.h. Inhaltsdaten zu verschlüsseln. Einer EncryptedData-Klasse kann ein ContentContainer oder wiederum ein EncryptedData-Objekt übergeben und mit den entsprechenden Methoden verschlüsselt werden. Die EncryptedData-Klasse stellt einen Datencontainer für verschlüsselte Daten in einer OSCI-Nachricht dar. Auch hier werden die wichtigen Informationen beim Konstruktor übergegeben.
Die Konstruktoren sehen folgendermaßen aus:
EncryptedData(javax.crypto.SecretKey secretKey, String encryptionMethodAlgorithm, ContentContainer coco)
Dieser Konstruktor bekommt ein SecretKey-Objekt zum symmetrischen Verschlüsseln der Inhaltsdaten, den symmetrischen Verschlüsselungsalgorithmus sowie den vorbereiteten Inhaltsdatencontainer (ContentContainer) mit den eigentlichen, zu verschlüsselnden Informationen.
Durch diese Konstruktoren sind die wichtigsten Informationen gesetzt. Für das eigentliche Verschlüsseln müssen folgende Methoden aufgerufen werden:
encrypt(de.osci.osci12.roles.Role reader)
Verschlüsselt den symmetrischen Schlüssel und fügt ihn als EncryptedKey-Element dem EncyptedDataOSCI-Element hinzu.
encrypt(byte[] encryptedSymKey,de.osci.osci12.roles.Role reader)
Es existiert bereits ein verschlüsselter symmetrischer Schlüssel, der hier übergeben werden kann. Als zweiter Parameter wird der Leser der Nachricht eingetragen.
Die encrypt-Methoden können mehrfach nacheinander aufgerufen werden um für weitere Adressaten zu verschlüsseln. Die hinzugefügten Empfänger-Zertifikate werden beim Hinzufügen des EncryptedData-Objekts zur OSCI-Nachricht übertragen.
Folgendes Sequenzdiagramm verdeutlicht das Erstellen eines verschlüsselten Inhaltsdatencontainers:
Im obigen Diagramm wird dem Konstruktor von EncryptedDataOSCI ein schon bestehender ContentContainer übergeben, ein neuer Leser erstellt und die Verschlüsselung des Inhaltsdatencontainers mit dem Zertifikat des Lesers durchgeführt.
Exemplarisch soll der Vorgang des Hinzufügens eines signierten und verschlüsselten Inhaltsdatencontainers zu einer Nachricht vorgestellt werden:
Erstellen eines Content-Objekts und Übergabe der XML-Inhaltsdaten an das Content-Objekt (n mal)
Hinzufügen der Content-Objekte zu dem ContentContainer
Signieren des ContentContainers mit dem übergebenen Author-Objekt
Einhängen des ContentContainers in ein EncryptedData-Objekt
Verschlüsseln des EncryptedData-Objekts (mit Hilfe eines Addressee-Objekts)
Hinzufügen des EncryptedData-Objekts zu der OSCI-Nachricht
Im Sourcecode sieht der Ablauf folgendermaßen aus:
// Vorbereitungen; Erstellen der Rollen-Objekte X509Certificate empfaenger = Tools.createCertificate(new FileInputStream("Empfaenger.cer")); de.osci.osci12.roles.Reader leser= new de.osci.osci12.roles.Reader(empfaenger); Addressee addressee = new Addressee(null, empfaenger); DialogHandler dialog=this.getDialogHandler(1); // Erstellen der OSCI-Nachricht mit ihren Rollen-Objekten StoreDelivery osci = new StoreDelivery(dialog, addressee); // Erstellen eines ContentContainers ContentContainer coco = new ContentContainer(); // Hinzufügen eines Contents coco.addContent(new Content("<xml>Inhaltsdaten in XML-Form</xml>")); // Signieren des Contentcontainers coco.sign(new Author (new AuthorSigner(),null), Constants.SIGNATURE_ALGORITHM_RSA_SHA1); // Erzeugen eines symmetrischen Schluessels javax.crypto.SecretKey secretKey = Crypto.createTDESKey(); // Erstellen eines Encrypteddata-OSCI-Objekts EncryptedDataOSCI encData= new EncryptedDataOSCI(secretKey, Constants.SYMMETRIC_CIPHER_ALGORITHM_TDES,coco); // Verschluesseln der Inhaltsdaten encData.encrypt(leser); // Hinzufuegen der fertigen Inhaltsdaten zur OSCI-Nachricht osci.addEncryptedData(encData);
Damit wurde eine einfach signierte, verschlüsselte Nachricht erstellt. Um Mehrfachverschlüsselung zu erreichen, müssen dem ContentContainer anstatt dem Content bereits verschlüsselte Nachrichten hinzugefügt werden.
Für das Versenden mit Mehrfachverschlüsselung (Vier-Augen-Prinzip) müssen folgende Schritte durchgeführt werden:
Erstellen eines Content-Objekts und Übergabe der XML-Inhaltsdaten an den Content (x mal)
Hinzufügen der Content-Objekte zu dem ContentContainer
Verschlüsseln des ContentContainers mit der EncryptedData-Klasse und dem ersten Reader-Objekt
Hinzufügen des EncryptedData-Objekts zu einem neuen ContentContainer
Erstellen eines neuen Content-Objekts und Hinzufügen der Content-Objekte zu dem ContentContainer
Signieren des zweiten ContentContainers mit dem übergebenen Author-Objekt
Verschlüsseln des zweiten ContentContainers mit der EncryptedData-Klasse und dem zweiten Reader-Objekt
Hinzufügen des EncryptedData-Objekts zu der OSCI-Nachricht
Entsprechend den Vorgaben der OSCI-Transport-1.2-Spezifikation wird zwischen Fehlermeldungen auf Nachrichtenebene und Rückmeldungen auf Auftragsebene unterschieden. Erstere stellen grundsätzlich echte Fehler dar. Sie werden von den auslösenden Methoden je nach Art des Fehlers durch eine der beiden folgenden Exceptions angezeigt:
SOAPClientException
SOAPServerException
Bei Rückmeldungen auf Auftragsebene wird zwischen Warnungen und Fehlern unterschieden. Während Erstere (OSCI-Code beginnend mit 9) eine Exception vom Typ OSCIErrorException auslösen, wird bei Warnungen (OSCI-Code beginnend mit 3) die Verarbeitung der betreffenden Nachricht fortgesetzt. Warnungen müssen von der Anwendung selbst durch Auswertung des Feedback-Eintrags der Antwortnachricht ermittelt werden.
Fehler, die innerhalb des Bibliothekscodes auftreten, werden durch verschiedene Exceptions angezeigt. Sofern es sich nicht um Exceptions der JAVA-API handelt, sind alle diese Exceptions von OSCIException abgeleitet und erben die o.g. Implementierung der Methode getMessage().
Die OSCI-Bibliothek besteht aus einer Vielzahl von Klassen, die in ihrer Gesamtheit die Szenarien der OSCI-Spezifikation abdecken sollen (Client- und Supplierseitig). Die Klassen der OSCI-Bibliothek sind alle in dem Package de.osci.osci12 untergebracht. Unterhalb dieses Packages befinden sich die Untergeordneten Packages, welche der Anwendungsentwickler benutzt. In dem folgenden Schaubild wird die Packagestruktur (mit ihren Klassen) dargestellt.
Erläuterung zu der Grafik:
de.osci.osci12.common. Dieses Package enthält allgemeine Klassen, welche zumeist von vielen anderen Klassen aus verschiedenen Packages benutzt werden. Package-übergreifende Klassen wie z.B der Dialog-Handler, die Default-Implementierung des DialogFinder und der DataSource-Klasse sowie allgemeine Konstanten und Helferklassen können in diesem Package gefunden werden.
de.osci.osci12.extinterfaces. Die externen Schnittstellen der Bibliothek. In diesem Package können alle externen Schnittstellen gefunden werden. Dies betrifft die Interfaces sowie die abstrakten Klassen der OSCI-Spezifikation. Weitere Informationen finden sich im Kapitel 'Schnittstellen'.
de.osci.osci12.messageparts. In diesem Package befinden sich OSCI-Nachrichtenbestandteile. Die in diesem Package zu findenden Klassen sind Bestandteile von OSCI-Nachrichten, welche in vielen Nachrichten Verwendung finden. Zu finden sind hier z.B. Repräsentationen der OSCI-Elemente Content-Container, Content, EncryptedData, Inspection, TimeStamp uvm.
de.osci.osci12.messagetypes. Dieses Package beinhaltet die Repräsentationen der OSCI-Nachrichtenobjekte. Für jede OSCI-Nachricht, ob Request oder Response, findet man in diesem Package eine gleichnamige Klasse. Weitere Informationen finden sich im Kapitel 'OSCI-Nachrichtenobjekte'.
de.osci.osci12.roles. Die Akteure der OSCI-Spezifikation. In diesem Package werden alle in der OSCI-Spezifikation erwähnten Akteure als JAVA-Klasse abgebildet. Weitere Informationen finden sich im Kapitel 'Akteure der OSCI-Bibliothek'.
Folgende Auflistung enthält weitere interne Packages, die vom Benutzer der OSCI-Bibliothek nicht direkt benutzt werden:
encryption
signature
soapheader
Use Case Nr. | 1 |
Use Case Name | Senden eines Zustellungsauftrags |
Geschäftsvorfall | Versand einer Nachricht in Form eines OSCI-Zustellauftrags |
Initiierender Aktor | Sender |
Weitere Aktoren | Intermediär |
Kurzbeschreibung | Versenden einer OSCI-Nachricht mit Inhaltsdatencontainer und Signaturen an den Intermediär |
Vorbedingungen |
|
Resultate | Zustellungsantwort mit Informationen zu dem Zustellungsauftrag |
| |
Alternative Pfade | Keine |
Fehlersituationen, Ausnahmen | OSCI-Fehlercodes des Typs 9*** lösen Exceptions aus; andere Fehler, Warnungen und Informationen können den OSCI-FeedBack-Objekten der Nachricht entnommen werden. |
Use Case Nr. | 2 |
Use Case Name | Senden eines Zustellungsabholauftrags |
Geschäftsvorfall | Ein Empfänger holt eine Nachricht aus seinem Postfach ab. |
Initiierender Aktor | Wegzugsmeldebehörde |
Weitere Aktoren | Intermediär |
Kurzbeschreibung | Abholen einer OSCI-Nachricht vom Intermediär als Empfänger/Leser |
Vorbedingungen |
|
Resultate | Zustellungsabholantwort mit dem Inhalt des Zustellungsauftrags |
| |
Alternative Pfade | Keine |
Fehlersituationen, Ausnahmen | Beim Prüfen der Inhaltsdatensignaturen und beim Decrypten des Inhaltsdatencontainers können Fehler auftreten, welche zu Exceptions führen. Auch beim Überprüfen des DialogControlblocks werden falsche Dialogkontexte durch Fehlermeldungen beantwortet. |
Use Case Nr. | 3 |
Use Case Name | Senden eines Weiterleitungsauftrags |
Geschäftsvorfall | Versand einer Nachricht in Form eines OSCI-Weiterleitungsauftrags |
Initiierender Aktor | Sender eines Weiterleitungsauftrags |
Weitere Aktoren | Intermediär |
Kurzbeschreibung | Versenden einer OSCI-Nachricht mit Inhaltsdatencontainer und Signaturen an den Intermediär. Als Ergebnis wird eine Antwort vom Fachverfahren erwartet. |
Vorbedingungen |
|
Resultate | Weiterleitungsantwort mit Informationen zur Weiterleitung. |
| |
Alternative Pfade | Keine |
Fehlersituationen, Ausnahmen | OSCI-Fehlercodes des Typs 9*** lösen Exceptions aus; andere Fehler, Warnungen und Informationen können dem OSCI-FeedBack-Objekten der Nachricht entnommen werden. |
Zurück | Zum Anfang | |
Der Auftrag der öffentlichen Verwaltung |