Elektronischer Datenaustausch mit der Deutschen Rentenversicherung

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:

UmgebungAdresse
Produktivumgebunghttps://itsg.eservice-drv.de/SPoC/ExtraService
Testumgebunghttps://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:

ArgumentBeschreibung
cmsOpenSSL soll eine CMS-Datenstruktur (PKCS#7) erzeugen.
-signEs handelt sich im eine SignedData Datenstruktur.
-binaryDie eingelesenen Daten sollen in binärem Format verarbeitet werden.
-in out_msg_plain.txtEs soll die angegebene Nachricht eingelesen werden.
-textDer ausgegebenen Nachricht werden Header für die MIME-Nachricht mitgegeben.
-nodetachDie signierten Daten sollen nicht im multipart/signed MIME-Typ kodiert werden.
-outform DERDie erzeugte CMS-Datenstruktur soll DER-kodiert (binär) ausgegeben werden.
-signer absender.pemDie erzeugte CMS-Datenstruktur soll mit der im angegebenen Zertifikat enthaltenen Identität signiert werden.
-certfile CAChain.pemEnthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können.
-inkey absender.keyVerweis auf den privaten Schlüssel des Absender-Zertifikats.
-out out_msg_signed.binDie erzeugte CMS-Datenstruktur soll in die angegebene Datei ausgegeben werden.
-keyopt rsa_padding_mode:pssAls Paddingmodus soll der von der GKV geforderte RSASSA-PSS Modus verwendet werden.
-nosmimecapStandardmäß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:

ArgumentBeschreibung
cmsOpenSSL soll eine CMS-Datenstruktur (PKCS#7) erzeugen.
-encryptEs handelt sich im eine verschlüsselte EnvelopedData Datenstruktur.
-binaryDie eingelesenen Daten sollen in binärem Format verarbeitet werden.
-in out_msg_signed.binEs soll die angegebene Nachricht eingelesen werden.
-aes-256-cbcFür die Verschlüsselung soll der AES-Algorithmus mit 256 Bit Schlüssellänge eingesetzt werden.
-out msg_encrypted.binDie erzeugte CMS-Datenstruktur soll in die angegebene Datei ausgegeben werden.
-outform DERDie erzeugte CMS-Datenstruktur soll DER-kodiert (binär) ausgegeben werden.
-recip empfaenger.pemGibt 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:oaepDie Schnittstellenbeschreibung der GKV verlangt, dass der OAEP-AES Paddingmodus zu verwenden ist.
-keyopt rsa_oaep_md:sha256Die 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:

ArgumentBeschreibung
cmsOpenSSL soll eine CMS-Datenstruktur (PKCS#7) verarbeiten.
-decryptEs handelt sich im eine EnvelopedData Datenstruktur, die entschlüsselt werden soll.
-inform DERDie CMS-Datenstruktur soll DER-kodiert (binär) eingelesen werden.
-in msg_encrypted.binDer Dateiname der zu verarbeitenden Nachricht.
-out in_msg_signed.binDer Dateiname der auszugebenden Nachricht.
-outform DERDie entschlüsselte Nachricht soll DER-kodiert (binär) ausgegeben werden.
-recip empfaenger.pemDie CMS-Datenstruktur soll mit der im angegebenen Zertifikat enthaltenen Identität entschlüsselt werden.
-inkey empfaenger.keyVerweis 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:

ArgumentBeschreibung
cmsOpenSSL soll eine CMS-Datenstruktur (PKCS#7) verarbeiten.
-verifyEs handelt sich im eine SignedData Datenstruktur, welche verifiziert werden soll.
-inform DERDie CMS-Datenstruktur soll DER-kodiert (binär) eingelesen werden.
-CAfile CAChain.pemEnthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können.
-in in_msg_signed.binDie Datei, in welcher die zu überprüfende CMS-Nachricht gespeichert ist.
-out in_msg_plain.txtDie 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:

ArgumentBeschreibung
-k https://itsg.eservicet-drv.de/SPoC/ExtraServiceDie Adresse des Webservice.
–cert empfaenger.pemDie Authentifizierung gegenüber dem Webservice soll mit dem angegebenen Zertifikat erfolgen.
–key empfaenger.keyVerweis auf den privaten Schlüssel des Authentisierungs-Zertifikats.
–cacert CAChain.pemEnthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können.
–tlsv1.2Es soll ausschließlich Transport Layer Security (TLS) in Version 1.2 verwendet werden.
-d @nachricht.xmlDie 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.txtDie 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:

ArgumentBeschreibung
-k https://itsg.eservicet-drv.de/SPoC/ExtraServiceDie Adresse des Webservice.
-X POSTAls HTTP-Methode soll POST verwendet werden.
–cert absender.pemDie Authentifizierung gegenüber dem Webservice soll mit dem angegebenen Zertifikat erfolgen.
–key absender.keyVerweis auf den privaten Schlüssel des Authentisierungs-Zertifikats.
–cacert CAChain.pemEnthält die Zertifikatkette der verwendeten Zertifikate, um den Vertrauensstatus zu diesen herstellen zu können.
–tlsv1.2Es soll ausschließlich Transport Layer Security (TLS) in Version 1.2 verwendet werden.
–data-binary @nachricht.xmlDie 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.txtDie 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

de_DEDeutsch