Jüngst habe ich zusammen mit der B-I-T GmbH Informationen und Prozesse aus Hannover daran gearbeitet, den elektronischen Datenaustausch mit den gesetzlichen Krankenkassen und der Rentenversicherung aus einer Anwendung heraus zu realisieren.
Hierbei wird eine Kombination aus authentifizierter Datenübertragung von sowohl signierten als auch verschlüsselten Nachrichten verwendet. In all diesen Fällen kommen PKI-Technologien zum Einsatz.
Das verwendete Nachrichtenformat ist hier dokumentiert.
Schematischer Ablauf der Kommunikation
Die Klartextnachricht ist eine XML-ähnliche Struktur (namens eXTra), welche hier nicht näher beschrieben wird. In diesem Artikel geht es rein um die notwendigen PKI-Operationen.
Siehe hierzu auch Artikel "Grundlagen Kryptographie".
Signierte Nachricht
Die im eXTra Format vorliegende Klartext-Nachricht wird in einer Cryptographic Message Syntax (CMS, auch bekannt als PKCS#7) SignedData Datenstruktur eingebettet. Diese Nachricht wird mit dem privaten Schlüssel des Absenders signiert, um die Integrität und Nichtabstreitbarkeit der Nachricht zu gewährleisten.
Verschlüsselte signierte Nachricht
Die signierte Nachricht wird anschließend in einer CMS (PKCS#7) EnvelopedData Datenstruktur eingebettet und mit den öffentlichen Schlüsseln der Empfänger (einer oder mehrere) verschlüsselt. Somit ist nun auch die Vertraulichkeit der Nachricht gewährleistet.
Schematisch dargestellt sieht die Nachricht nun somit in etwa wie folgt aus:
Datenübertragung der verschlüsselten signierten Nachricht
Die verschlüsselte signierte Nachricht wird nun über einen der folgenden Wege gesendet oder abgeholt:
- Über einen Web Service im Falle der Rentenversicherung.
- Per E-Mail im Falle der gesetzlichen Krankenkassen.
Im Weiteren Verlauf wird nur die Rentenversicherung betrachtet, im Falle der gesetzlichen Krankenversicherung verhalten sich die Abläufe aber weitestgehend gleich.
Die Rentenversicherung setzt folgende Web Services ein:
Umgebung | Adresse |
---|---|
Produktivumgebung | https://itsg.eservice-drv.de/SPoC/ExtraService |
Testumgebung | https://itsg.eservicet-drv.de/SPoC/ExtraService |
Schematisch dargestellt müssen über die gesamte Kommunikationskette hinweg insgesamt also die folgenden Operationen vorgenommen werden:
Umsetzung
Unser erster Ansatz war, eine Kommandozeilenanwendung in C# zu schreiben, welche die Erstellung/Prüfung der Signaturen und die Ver-/Entschlüsselung der Nachrichten vornimmt. Dies hätte den Vorteil, dass man auf die Windows Zertifikats-API zugreifen könnte und somit im Backend zum Beispiel die verwendeten Zertifikate auf einer Smartcard oder einem Trusted Platform Modul sichern könnte.
C# (und PowerShell) scheiden allerdings leider aus, da bei der benötigten CmsSigner Klasse das Paddingschema nicht vorgegeben werden kann, und die GKV RSASSA-PSS (PKCS#1 Version 2.1) vorschreibt.
Die Werkzeuge der Wahl heißen daher OpenSSL und cURL. Auch hier gibt es die Möglichkeit, beispielsweise über die PKCS#11 Schnittstelle eine Smartcard im Backend zu verwenden. Der Einfachkeit halber wird nachfolgend allerdings das Vorgehen mit einfachen Schlüsseldateien beschrieben.
Umwandlung in die passenden Dateiformate
Zunächst müssen die Zertifikate im entsprechenden Format vorliegen.
Folgende Annahmen werden getroffen:
- Das zum Signieren und Entschlüsseln verwendete Zertifikat liegt im BASE64-kodierten DER-Format (PEM) vor.
- Der private Schlüssel des Zertifikats liegt ohne Passwort ebenfalls im BASE64-kodierten DER-Format (PEM) vor.
- Es liegt eine Datei vor, welche alle beteiligten Zertifizierungsstellen-Zertifikate ebenfalls im BASE64-kodierten DER-Format (PEM) beinhaltet, vor.
Nachricht signieren
Mit nachfolgendem Befehl wird die in der Datei out_msg_plain.txt enthaltene Nachricht signiert und die entstandene signierte Nachricht in die Datei out_msg_signed.bin gespeichert. Zum Signieren der Nachricht wird das Zertifikat des Absenders (absender.pem) verwendet, zu welchem der private Schlüssel (absender.key) vorliegen muss.
openssl ^ cms ^ -sign ^ -binary ^ -in out_msg_plain.txt ^ -text ^ -nodetach -outform DER ^ -signer absender.pem ^ -certfile CAChain.pem ^ -inkey absender.key ^ -out out_msg_signed.bin ^ -keyopt rsa_padding_mode:pss ^ -nosmimecap
Um die Lesbarkeit des Befehls zu verbessern, wurden Zeilenumbrüche der Windows-Kommandozeile eingetragen.
Die verwendeten Argumente haben folgende Bedeutung:
Argument | Beschreibung |
---|---|
cms | OpenSSL soll eine CMS-Datenstruktur (PKCS#7) erzeugen. |
-sign | Es handelt sich im eine SignedData Datenstruktur. |
-binary | Die eingelesenen Daten sollen in binärem Format verarbeitet werden. |
-in out_msg_plain.txt | Es soll die angegebene Nachricht eingelesen werden. |
-text | Der ausgegebenen Nachricht werden Header für die MIME-Nachricht mitgegeben. |
-nodetach | Die signierten Daten sollen nicht im multipart/signed MIME-Typ kodiert werden. |
-outform DER | Die erzeugte CMS-Datenstruktur soll DER-kodiert (binär) ausgegeben werden. |
-signer absender.pem | Die erzeugte CMS-Datenstruktur soll mit der im angegebenen Zertifikat enthaltenen Identität signiert werden. |
-certfile CAChain.pem | Enthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können. |
-inkey absender.key | Verweis auf den privaten Schlüssel des Absender-Zertifikats. |
-out out_msg_signed.bin | Die erzeugte CMS-Datenstruktur soll in die angegebene Datei ausgegeben werden. |
-keyopt rsa_padding_mode:pss | Als Paddingmodus soll der von der GKV geforderte RSASSA-PSS Modus verwendet werden. |
-nosmimecap | Standardmäßig hängt OpenSSL eine S/MIME Capabilities Erweiterung an die Datenstruktur (da eine signierte Mail identisch aufgebaut ist), dieses Verhalten wird mit dieser Option unterbunden. |
Nachricht verschlüsseln
An dieser Stelle muss erwähnt werden, dass wir im Echtbetrieb natürlich sowohl Absender als auch Empfänger von Nachrichten sind. In diesem Fall verwenden wir für das Versenden und Empfangen von Nachrichten jeweils das gleiche Zertifikat samt privatem Schlüssel. Nachfolgend wird jedoch abweichend der Dateiname "empfaenger.pem" verwendet, da wir beispielsweise in einer Entwicklungs- oder Testumgebung das Versenden und Empfangen der gleichen Nachricht simulieren möchten.
Mit nachfolgendem Befehl wird die in der Datei out_msg_signed.bin gespeicherte signierte Nachricht verschlüsselt und die darin entstehende signierte Nachricht in die Datei out_msg_encrypted.bin gespeichert. Zum Verschlüssel wird das Zertifikat des Empfängers (empfaenger.pem) ohne privaten Schlüssel benötigt.
openssl ^ cms ^ -encrypt ^ -binary ^ -in out_msg_signed.bin ^ -aes-256-cbc ^ -out msg_encrypted.bin ^ -outform DER ^ -recip empfaenger.pem ^ -keyopt rsa_padding_mode:oaep ^ -keyopt rsa_oaep_md:sha256
Um die Lesbarkeit des Befehls zu verbessern, wurden Zeilenumbrüche der Windows-Kommandozeile eingetragen.
Die verwendeten Argumente haben folgende Bedeutung:
Argument | Beschreibung |
---|---|
cms | OpenSSL soll eine CMS-Datenstruktur (PKCS#7) erzeugen. |
-encrypt | Es handelt sich im eine verschlüsselte EnvelopedData Datenstruktur. |
-binary | Die eingelesenen Daten sollen in binärem Format verarbeitet werden. |
-in out_msg_signed.bin | Es soll die angegebene Nachricht eingelesen werden. |
-aes-256-cbc | Für die Verschlüsselung soll der AES-Algorithmus mit 256 Bit Schlüssellänge eingesetzt werden. |
-out msg_encrypted.bin | Die erzeugte CMS-Datenstruktur soll in die angegebene Datei ausgegeben werden. |
-outform DER | Die erzeugte CMS-Datenstruktur soll DER-kodiert (binär) ausgegeben werden. |
-recip empfaenger.pem | Gibt das Zertifikat des Empfängers der Nachricht an. Mit dem dazugehörigen öffentlichen Schlüssel wird die Nachricht verschlüsselt. Der Parameter kann mehrmals angegeben werden, wenn die Nachricht an mehrere Empfänger gesendet werden soll. |
-keyopt rsa_padding_mode:oaep | Die Schnittstellenbeschreibung der GKV verlangt, dass der OAEP-AES Paddingmodus zu verwenden ist. |
-keyopt rsa_oaep_md:sha256 | Die Schnittstellenbeschreibung der GKV verlangt, dass der Hashalgorithmus SHA-256 zu verwenden ist. |
Bitte beachten: Wenn der Absender sich selbst nicht auch in die Liste der Empfänger einträgt, wird er selbst nicht imstande sein, die erzeugte Nachricht zu entschlüsseln. In der Regel gibt es hierfür ja auch keinen Anlass, dieser Umstand kann allerdings leicht zu Verwirrung führen.
Nachricht entschlüsseln
Mit nachfolgendem Befehl wird die in der Datei in_msg_encrypted.bin gespeicherte Nachricht entschlüsselt und die darin enthaltene signierte Nachricht in die Datei in_msg_signed.bin gespeichert. Zum Entschlüsseln wird das Zertifikat des Empfängers (empfaenger.pem) samt privatem Schlüssel (empfaenger.key) benötigt
openssl ^ cms ^ -decrypt ^ -inform DER ^ -in in_msg_encrypted.bin ^ -out in_msg_signed.bin ^ -outform DER ^ -recip empfaenger.pem ^ -inkey empfaenger.key
Um die Lesbarkeit des Befehls zu verbessern, wurden Zeilenumbrüche der Windows-Kommandozeile eingetragen.
Die verwendeten Argumente haben folgende Bedeutung:
Argument | Beschreibung |
---|---|
cms | OpenSSL soll eine CMS-Datenstruktur (PKCS#7) verarbeiten. |
-decrypt | Es handelt sich im eine EnvelopedData Datenstruktur, die entschlüsselt werden soll. |
-inform DER | Die CMS-Datenstruktur soll DER-kodiert (binär) eingelesen werden. |
-in msg_encrypted.bin | Der Dateiname der zu verarbeitenden Nachricht. |
-out in_msg_signed.bin | Der Dateiname der auszugebenden Nachricht. |
-outform DER | Die entschlüsselte Nachricht soll DER-kodiert (binär) ausgegeben werden. |
-recip empfaenger.pem | Die CMS-Datenstruktur soll mit der im angegebenen Zertifikat enthaltenen Identität entschlüsselt werden. |
-inkey empfaenger.key | Verweis auf den privaten Schlüssel des Empfänger-Zertifikats. |
Signatur prüfen und Klartext ausgeben
Mit nachfolgendem Befehl wird die Signatur der in der Datei in_msg_signed.bin enthaltenen CMS-Nachricht überprüft und die Klartextnachricht in die Datei in_msg_plain.txt gespeichert.
openssl ^ cms ^ -verify ^ -inform DER ^ -CAfile CAChain.pem ^ -in in_msg_signed.bin ^ -out in_msg_plain.txt
Um die Lesbarkeit des Befehls zu verbessern, wurden Zeilenumbrüche der Windows-Kommandozeile eingetragen.
Die verwendeten Argumente haben folgende Bedeutung:
Argument | Beschreibung |
---|---|
cms | OpenSSL soll eine CMS-Datenstruktur (PKCS#7) verarbeiten. |
-verify | Es handelt sich im eine SignedData Datenstruktur, welche verifiziert werden soll. |
-inform DER | Die CMS-Datenstruktur soll DER-kodiert (binär) eingelesen werden. |
-CAfile CAChain.pem | Enthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können. |
-in in_msg_signed.bin | Die Datei, in welcher die zu überprüfende CMS-Nachricht gespeichert ist. |
-out in_msg_plain.txt | Die Datei, in welche die Klartextnachricht gespeichert werden soll. |
Datenübertragung
Übertragung der Daten zum Webservice und Authentifizierung via Zertifikat.
Auch hier werden in den Beispielen aus Verständnisgründen zwei Zertifikate (absender.pem und empfaenger.pem) genannt, im Echtbetrieb handelt es sich natürlich in beiden Fällen um das gleichen Zertifikat.
cURL ist in aktuellen Windows 10 Builds fester Bestandteil des Betriebssystems und muss nicht gesondert installiert werden.
Abruf von Daten
Die signierten und verschlüsselten Nutzdaten werden als MTOM-Objekt mit der SOAP-Nachricht versendet.
curl ^ -k https://itsg.eservicet-drv.de/SPoC/ExtraService ^ --cert empfaenger.pem ^ --key empfaenger.key ^ --cacert CAChain.pem ^ --tlsv1.2 ^ -d @nachricht.xml ^ -H "Content-Type: application/soap+xml" ^ -o Outfile.txt
Um die Lesbarkeit des Befehls zu verbessern, wurden Zeilenumbrüche der Windows-Kommandozeile eingetragen.
Die verwendeten Argumente haben folgende Bedeutung:
Argument | Beschreibung |
---|---|
-k https://itsg.eservicet-drv.de/SPoC/ExtraService | Die Adresse des Webservice. |
–cert empfaenger.pem | Die Authentifizierung gegenüber dem Webservice soll mit dem angegebenen Zertifikat erfolgen. |
–key empfaenger.key | Verweis auf den privaten Schlüssel des Authentisierungs-Zertifikats. |
–cacert CAChain.pem | Enthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können. |
–tlsv1.2 | Es soll ausschließlich Transport Layer Security (TLS) in Version 1.2 verwendet werden. |
-d @nachricht.xml | Die MTOM-Nachricht, welche die verschlüsselten und signierten Nutzdaten enthält. |
-H "Content-Type: application/soap+xml" | Gibt über HTTP-Header an, welcher Art Daten übertragen werden. |
-o Outfile.txt | Die Ausgabe des Webservice wird in die angegebene Datei umgeleitet. |
Versenden von Daten
Die signierten und verschlüsselten Nutzdaten werden als MTOM-Objekt mit der SOAP-Nachricht versendet.
Um die Lesbarkeit des Befehls zu verbessern, wurden Zeilenumbrüche der Windows-Kommandozeile eingetragen.
curl ^ -k https://itsg.eservicet-drv.de/SPoC/ExtraService ^ -X POST ^ --cert absender.pem ^ --key absender.key ^ --cacert CAChain.pem ^ --tlsv1.2 ^ --data-binary @nachricht.xml ^ -H "content-type: multipart/related; boundary=MIME-Multipart-Boundary;Content-ID=RootPart; charset=iso-8859-1;" ^ -o Outfile.txt
Die verwendeten Argumente haben folgende Bedeutung:
Argument | Beschreibung |
---|---|
-k https://itsg.eservicet-drv.de/SPoC/ExtraService | Die Adresse des Webservice. |
-X POST | Als HTTP-Methode soll POST verwendet werden. |
–cert absender.pem | Die Authentifizierung gegenüber dem Webservice soll mit dem angegebenen Zertifikat erfolgen. |
–key absender.key | Verweis auf den privaten Schlüssel des Authentisierungs-Zertifikats. |
–cacert CAChain.pem | Enthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können. |
–tlsv1.2 | Es soll ausschließlich Transport Layer Security (TLS) in Version 1.2 verwendet werden. |
–data-binary @nachricht.xml | Die MTOM-Nachricht, welche die verschlüsselten und signierten Nutzdaten enthält. |
-H "content-type: multipart/related; boundary=MIME-Multipart-Boundary;Content-ID=RootPart; charset=iso-8859-1;" | Gibt über HTTP-Header an, welcher Art Daten übertragen werden. |
-o Outfile.txt | Die Ausgabe des Webservice wird in die angegebene Datei umgeleitet. |
Einige Tipps für die Fehlersuche
Analyse einer Nachricht
Zwecks Analyse und Fehlersuche ist es sehr hilfreich, das Zertifikat im Windows-Zertifikatspeicher samt privatem Schlüssel vorzuhalten.
Die Nachricht kann anschließend mit folgendem Befehl ausgewertet werden:
certutil -dump {Datei}
Der Inhalt einer verschlüsselten CMS-Nachricht kann direkt mit folgendem Befehl entpackt werden:
certutil -strip {Datei}
Weiterführende Links:
Externe Quellen
- Security Schnittstelle (SECON) (Elektronischer Datenaustausch in der gesetzlichen Krankenversicherung)
- Schnittstellenspezifikation zum XML-basierenden, elektronischen Datenaustausch mit der Rentenversicherung im Verfahren Reha§301 (Deutsche Rentenversicherung Bund)
- Data Exchange in the German Health Service with CryptoSys PKI (D.I. Management Services Pty Limited)
- tinyHeb, Eine Open Source Abrechnungssoftware für Hebammen
- RFC 5652 – Cryptographic Message Syntax (CMS) (Internet Engineering Task Force)