diff --git a/docs/getting-started/schema-validation.mdx b/docs/getting-started/schema-validation.mdx index dee492105de197852701199eb7dfd33ae0d0cc1f..fec581153f8ef58404c5d708716adc2ebb657a82 100644 --- a/docs/getting-started/schema-validation.mdx +++ b/docs/getting-started/schema-validation.mdx @@ -5,268 +5,6 @@ title: Schemavalidierung import Tabs from '@theme/Tabs' import TabItem from '@theme/TabItem' -## Sicherstellung der Integrität einer Submission - -<!-- Allgemeine Beschreibung für Sender + Subscriber --> -Es muss sichergestellt sein, dass Zwischensysteme, wie z. B. auch FIT-Connect selbst, Fachdaten -oder Anhänge von Submissions nicht austauschen. Hierfür wird eine Hashfunktion verwendet, welche -die Integrität der Datensätze prüfbar macht. Die so berechneten Hashes werden in den Metadaten -verschlüsselt abgelegt und können bei Abruf vom Subscriber validiert werden. - -Nur wenn sowohl der Sender als auch der Subscriber Ihre Aufgaben übernehmen, ist die Integrität -einer Submission sichergestellt. -Wie diese Aufgaben im Detail aussehen, soll im Folgenden beschrieben werden. - -### Aufgaben des Senders -Vor dem Versenden des Antrags muss der Sender sowohl für die Fachdaten als auch für jeden einzelnen Anhang den Hashwert berechnen. -Starten wir mit den **Fachdaten**: - -1. Prüfen, ob **Fachdaten** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. -2. Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512) aus den Fachdaten. -3. Schreiben des Hashtyps sowie des Hashwertes in die Metadaten unter `.data.hash`. - -Nun zu den **Anhängen**: - -1. Prüfen, ob **Anhänge** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. -2. Für jeden Anhang: Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512). -3. Für jeden Anhang: Schreiben des Hashtyps sowie des Hashwertes in die Metadaten unter `.attachments.*.hash`. - -<Tabs - defaultValue="java" - groupId="code-examples" - values={[ - { label: 'CLI', value: 'cli', }, - { label: 'Java', value: 'java', }, - { label: 'Python', value: 'python', }, - { label: '.NET', value: 'dotnet', }, - ] -}> - <TabItem value="cli"> - - ```bash - # Ohne Dateinamen am Ende - ➜ sha512sum fachdaten.json | cut -d' ' -f1 - 92aae16fa71f045b482dafdfa12aed8dc502945444367e78600bb48df32d2b4be01e805c923cc8de11992616666cc80e9e133b73b1f234f8a27688a61ab065a9 - ``` - </TabItem> - - <TabItem value="java"> - - Der vollständige Beispielcode kann [im Beispielcoderepository unter `/java/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/java/metadata-verifier) - gefunden werden. - - ```java - MetadataVerifier metadataVerifier = new MetadataVerifier(); - - byte[] exampleFileContent = MetadataVerifier.class.getResourceAsStream("/example.pdf").readAllBytes(); - - // Sender: create hash of data (Fachdaten) or attachments (Anhänge) for Metadata - byte[] hash = metadataVerifier.createHash(exampleFileContent); - String hexHash = MetadataVerifier.toHexString(hash); // Optional - System.out.printf("Sender: {\"type\": \"sha512\", \"content\": \"%s\"}\n", hexHash); - ``` - - </TabItem> - <TabItem value="python"> - - Der vollständige Beispielcode kann [im Beispielcoderepository unter `/python/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/python/metadata-verifier) - gefunden werden. - - ```python - import hashlib - import json - - def create_hash(data: bytes): - return hashlib.sha512(data) - - def sender(example_pdf): - with open(example_pdf, "rb") as file_to_send: - file_to_send_bytes = file_to_send.read() - file_to_send_hash = create_hash(file_to_send_bytes) - print( - json.dumps( - {"type": "sha512", "content": file_to_send_hash.hexdigest()}, indent=4 - ) - ) - ``` - - </TabItem> - <TabItem value="dotnet"> - - Der vollständige Beispielcode kann [im Beispielcoderepository unter `/dotnet/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/dotnet/metadata-verifier) - gefunden werden. - - ```csharp - using System; - using System.Security.Cryptography; - using System.Reflection; - using System.Text.Json; - - using (Stream? inputData = Assembly.GetExecutingAssembly().GetManifestResourceStream("example.pdf")) - { - if (inputData == null) - { - Console.Error.WriteLine("Error reading file from assembly."); - return; - } - using (var hashFunction = SHA512.Create()) - { - byte[] hash = hashFunction.ComputeHash(inputData); - String hashAsString = BitConverter.ToString(hash) - .Replace("-", "") - .ToLowerInvariant(); - - Console.WriteLine("Sender: " + JsonSerializer.Serialize(new - { - type = "sha512", - content = hashAsString - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - ``` - - </TabItem> -</Tabs> - -### Aufgaben des Subscribers - -<!-- Aufgaben des Subscribers --> -Nachdem ein Antrag empfangen wurde und **vor** dessen Weiterverwendung, muss die Integrität der Fachdaten und Anhänge sichergestellt werden. -Starten wir mit den **Fachdaten**: - -1. Prüfen, ob **Fachdaten** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. -2. Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512) aus den Fachdaten. -3. Prüfen, ob dieser Hash mit dem aus den Metadaten übereinstimmt (Feld `.data.hash.content`). - - a. Wenn ja: Die Integrität der Fachdaten ist sichergestellt. - b. Wenn nein: Die Integrität der Fachdaten ist nicht gestellt. Die Fachdaten wurden durch ein Zwischensystem verändert! - -<!-- TODO: Beschreibung, was im Fall einer Integritätsverletzung getan werden sollte. --> - -Nun zu den **Anhängen**: - -1. Prüfen, ob **Anhänge** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. -2. Für jeden Anhang: Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512). -3. Für jeden Anhang: Prüfen, ob dieser Hash mit dem aus den Metadaten übereinstimmt (Feld `.attachments.*.hash.content`). - - a. Wenn ja: Die Integrität des Anhangs ist sichergestellt. - b. Wenn nein: Die Integrität des Anhangs ist nicht gestellt. Der Anhang wurden durch ein Zwischensystem verändert! - -<!-- TODO: Beschreibung, was im Fall einer Integritätsverletzung getan werden sollte. --> - -<Tabs - defaultValue="java" - groupId="code-examples" - values={[ - { label: 'CLI', value: 'cli', }, - { label: 'Java', value: 'java', }, - { label: 'Python', value: 'python', }, - { label: '.NET', value: 'dotnet', }, - ] -}> - <TabItem value="cli"> - - ```bash - ➜ HASH="92aae16fa71f045b482dafdfa12aed8dc502945444367e78600bb48df32d2b4be01e805c923cc8de11992616666cc80e9e133b73b1f234f8a27688a61ab065a9" - - # Erfolgreiche Hashvalidierung. Integrität der Fachdaten sichergestellt. - ➜ echo "$HASH fachdaten.json" | sha512sum --check - fachdaten.json: OK - - # Fehlgeschlagene Hashvalidierung. Integrität der Fachdaten fehlerhaft. - # Der Hash wurde manuell modifiziert (und dadurch ungültig gemacht). - ➜ INVALID_HASH=00000000001f045b482dafdfa12aed8dc502945444367e78600bb48df32d2b4be01e805c923cc8de11992616666cc80e9e133b73b1f234f8a27688a61ab065a8 - ➜ echo "$INVALID_HASH fachdaten.json" | sha512sum --check - fachdaten.json: FAILED - sha512sum: WARNING: 1 computed checksum did NOT match - ``` - - </TabItem> - - <TabItem value="java"> - - Der vollständige Beispielcode kann [im Beispielcoderepository unter `/java/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/java/metadata-verifier) - gefunden werden. - - ```java - MetadataVerifier metadataVerifier = new MetadataVerifier(); - - byte[] exampleFileContent = MetadataVerifier.class.getResourceAsStream("/example.pdf").readAllBytes(); - - // Subscriber: verify Hash of data (Fachdaten) or attachments (Anhänge) - String hashFromSender = "bf85bd96831e5df2200b76a8c7e3c74044e96bc30d1ffc3d1c4b05d4ee5b258714ab28a4ee12c9eb7f7cec1878d49036f4ccaf809a6c9545707fb1b91f2676ae"; - boolean verify = metadataVerifier.verify(metadataVerifier.fromHexString(hashFromSender), exampleFileContent); - System.out.printf("Subscriber: Verification %s\n", verify ? "OK" : "FAILED"); - ``` - - </TabItem> - <TabItem value="python"> - - Der vollständige Beispielcode kann [im Beispielcoderepository unter `/python/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/python/metadata-verifier) - gefunden werden. - - ```python - import hashlib - import json - - def create_hash(data: bytes): - return hashlib.sha512(data) - - def verify_hash(original_hash: bytes, data: bytes) -> bool: - new_hash = create_hash(data).digest() - return original_hash == new_hash - - hash_from_sender = "bf85bd96831e5df2200b76a8c7e3c74044e96bc30d1ffc3d1c4b05d4ee5b258714ab28a4ee12c9eb7f7cec1878d49036f4ccaf809a6c9545707fb1b91f2676ae" - with open(example_pdf, "rb") as data_from_sender: - data_from_sender_bytes = data_from_sender.read() - - verify_ok = verify_hash(bytes.fromhex(hash_from_sender), data_from_sender_bytes) - print(f"Subscriber: Verification {'OK' if verify_ok else 'FAILED'}") - ``` - - </TabItem> - <TabItem value="dotnet"> - - Der vollständige Beispielcode kann [im Beispielcoderepository unter `/dotnet/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/dotnet/metadata-verifier) - gefunden werden. - - ```csharp - using System; - using System.Security.Cryptography; - using System.Reflection; - - string hashFromSender = "bf85bd96831e5df2200b76a8c7e3c74044e96bc30d1ffc3d1c4b05d4ee5b258714ab28a4ee12c9eb7f7cec1878d49036f4ccaf809a6c9545707fb1b91f2676ae"; - - using (Stream? inputData = Assembly.GetExecutingAssembly().GetManifestResourceStream("example.pdf")) - { - if (inputData == null) - { - Console.Error.WriteLine("Error reading file from assembly."); - return; - } - using (var hashFunction = SHA512.Create()) - { - byte[] hash = hashFunction.ComputeHash(inputData); - byte[] comparisonHash = Convert.FromHexString(hashFromSender); - - Console.Write("Subscriber: Verification "); - if (hash.SequenceEqual(comparisonHash)) - { - Console.WriteLine("OK"); - } - else - { - Console.WriteLine("FAILED"); - } - } - - } - ``` - - </TabItem> -</Tabs> - - ## Validierung des Metadatensatzes :::caution diff --git a/docs/getting-started/submission/metadata.mdx b/docs/getting-started/submission/metadata.mdx index 50727d0b152d4266f5ab4293aea0c200b9101f9c..a0196153c663521b3e1746549bb3c473fa4b7fed 100644 --- a/docs/getting-started/submission/metadata.mdx +++ b/docs/getting-started/submission/metadata.mdx @@ -3,17 +3,10 @@ title: Metadatensatz --- Die Antragsmetadaten beschreiben die Struktur der Einreichung und deren Inhalte, wie Anhänge oder Fachdaten. -Zusätzlich können weitere Informationen über Verwaltungskund:innen hinterlegt werden. -Eine genaue Definition ist in der [Schema-Beschreibung](../../metadata/overview.mdx) zu finden. -Im Folgenden wird nun beschrieben, wie für das Versenden einer Einreichung das Schema aufgebaut und befüllt wird. +Der Metadatensatz enthält ebenfalls Hashwerte der übermittelten Fachdaten und Anlagen, um einen [bösartigen Austausch von einzelnen Anlagen](../../sending/metadata.mdx#integrity) zu verhindern. -Das Minimum, was an Information in den Metadaten vorhanden sein muss, ist der Abschnitt `contentStructure`. -In diesem muss angegeben werden, ob und in welchem Format ein Fachdatensatz mit versendet wird. -Des Weiteren können Anhänge beschrieben werden, die der Einreichung beigefügt sind. - -Sollten weitere Informationen notwendig sein (z.B. Rückkanal, Bezahlinformationen, ...), können weitere -im Metadatenschema definierte Felder befüllt und mitversendet werden. -Ob diese jedoch ausgewertet werden, hängt vom Empfänger bzw. dessen unterstützter Metadatenschemaversion ab. +Zusätzlich können weitere Informationen, z.B. über die antragstellende Verwaltungskund:in hinterlegt werden. +Eine genaue Definition und weitere Informationen sind in der [Schema-Beschreibung zum Metadatensatz](../../metadata/overview.mdx) zu finden. :::tip Hinweis Die einzelnen Abschnitte des Metadatensatzes werden [hier](../../metadata/overview.mdx) diff --git a/docs/metadata/contentStructure.mdx b/docs/metadata/contentStructure.mdx index fb38442e06950e26d86f1599ff7a27a11455a2c3..b6611ae7e1eebd98b9e6b51edcedcd9c034deee5 100644 --- a/docs/metadata/contentStructure.mdx +++ b/docs/metadata/contentStructure.mdx @@ -1,7 +1,7 @@ ## Inhaltsstruktur (`contentStructure`) -Im Objekt der Inhaltsstruktur werden alle zusätzlichen Inhalte, die zu der Einreichung gehören, wie Anlagen oder -Fachdaten, beschrieben. +Im Abschnitt `contentStructure` des Metadatensatzes einer Einreichung wird die Struktur der Einreichung und deren Inhalte, wie Anhänge oder Fachdaten, beschrieben. +In diesem Abschnitt sind zudem Hashwerte der übermittelten Fachdaten und Anlagen enthalten, um einen [bösartigen Austausch von einzelnen Anlagen](../sending/metadata.mdx#integrity) zu verhindern. <!-- https://git.fitko.de/fit-connect/metadata-schema/-/blob/main/examples/schwerbehindertenausweis.example.json --> ```json diff --git a/docs/metadata/overview.mdx b/docs/metadata/overview.mdx index 21e3b3c6ebc92450a8ce0028c1c3ff2c20371432..7c9ee2709f93b64c4b3d3c3370b057939ed95d8a 100644 --- a/docs/metadata/overview.mdx +++ b/docs/metadata/overview.mdx @@ -6,18 +6,27 @@ hide_table_of_contents: true import JSONSchema from '@views/JSONSchema' Metadaten sind ein zentraler Bestandteil einer Einreichung. -Sie beschreiben die Struktur der Einreichung und deren Inhalte, wie beispielsweise Anlagen oder die Fachdaten. -Zusätzlich können weitere Informationen über d:ie Verwaltungskund:in hinterlegt werden. -Eine genaue Definition ist in der [Schema-Definition](#metadatenschema) zu finden. +Sie beschreiben die Struktur der Einreichung und deren Inhalte, wie Anlagen oder Fachdaten. +Zusätzlich können weitere Informationen, z.B. über die antragstellende Verwaltungskund:in hinterlegt werden. +Eine genaue Definition ist [in der Schema-Definition](#metadata-schema) zu finden (siehe unten). Im Folgenden werden nun die großen Bereiche, die im Metadatenschema aufgeführt werden, grob beschrieben. +Details zu den einzelnen Abschnitten finden sich im jeweiligen Unterkapitel. + +Das Metadaten-Schema validiert gegen und orientiert sich an der [JSON Schema Spezifikation 2020-12](https://json-schema.org/specification-links.html#2020-12) in der Version von 2020. +Es besteht primär aus den fünf Bereichen Authentifizierungsinformationen, Inhaltsstruktur, Bezahlinformationen, Verwaltungsleistung und Rückkanal. + +Das Minimum, was an Information in den Metadaten vorhanden sein muss, ist der Abschnitt [`contentStructure`](contentStructure.mdx). +In diesem muss angegeben werden, ob und in welchem Format ein Fachdatensatz mit versendet wird. +Des Weiteren können Anhänge beschrieben werden, die der Einreichung beigefügt sind. +In diesem Abschnitt sind zudem Hashwerte der übermittelten Fachdaten und Anlagen enthalten, um einen [bösartigen Austausch von einzelnen Anlagen](../sending/metadata.mdx#integrity) zu verhindern. + +Sollten weitere Informationen notwendig sein (z.B. Rückkanalinformationen, Bezahlinformationen, ...), dann können weitere im Metadatenschema definierte Felder befüllt und mitversendet werden. +Ob diese jedoch ausgewertet werden, hängt vom Empfänger bzw. dessen unterstützter Metadatenschemaversion ab. :::tip Hinweis Ein Beispiel für den Metadatensatz eines Kindergeldantrags findet sich in der [Dokumentation zum Aufbau einer Einreichung](../getting-started/submission/metadata.mdx) ::: -Das Metadaten-Schema validiert gegen und orientiert sich an der [JSON Schema Spezifikation 2020-12](https://json-schema.org/specification-links.html#2020-12) in der Version von 2020. -Es besteht primär aus den fünf Bereichen Authentifizierungsinformationen, Inhaltsstruktur, Bezahlinformationen, Verwaltungsleistung und Rückkanal. - -## Metadatenschema +## Schema-Definition des Metadatenschema {#metadata-schema} <JSONSchema version={"1.*.*"} name="metadata" /> diff --git a/docs/receiving/verification.mdx b/docs/receiving/verification.mdx index 70d4d68db88974e47097368036953c6ff5e49660..c4767d309fde0ac9d5ccee136d611581ac98ad00 100644 --- a/docs/receiving/verification.mdx +++ b/docs/receiving/verification.mdx @@ -9,8 +9,9 @@ import TabItem from '@theme/TabItem' Nachdem das empfangende System eine Einreichung empfangen hat, muss es diese überprüfen. Nach der Überprüfung muss entweder ein Empfangsbestätigung ("accept submission") oder Zurückweisung ("reject submission") gesendet werden. +Dies ist wichtig, um neben der Prüfung von technischen Fehlern auch einen [bösartigen Austausch von einzelnen Anlagen](#integrity) zu verhindern. -Eine Rückweisung könnte wie folgt aussehen. +Eine Rückweisung des empfangenden Systems aufgrund einer fehlgeschlagenen Prüfung könnte wie folgt aussehen. ```json { @@ -57,16 +58,15 @@ Die Angabe `detail` KANN ergänzt oder ersetzt werden, sofern zur Fehlerbehebung stehen. :::caution Hinweis - Alle Informationen im Problem-Datensatz werden an das sendende System gesendet, das sie zur Fehlerbehebung speichert. Die Fehlermeldungen dürfen den Nutzern des Systems (z.B. Bürgern, die einen Online-Antrag nutzen) nicht angezeigt werden! - ::: -## Überprüfung der Einreichung - -### Überprüfung des Event-Logs +## Überprüfung des Event-Logs +Zunächst MUSS eine Prüfung des Ereignisprotokolls der jeweiligen Einreichung erfolgen. +Hierbei sind die folgenden Punkte zu beachten: +### Struktur- und Signaturprüfung der Security-Event-Tokens Rufen Sie das Event-Log unter <ApiLink api="submission-api" withMethod="get" to="/v1/cases/{caseId}/events" /> ab. Prüfen Sie die Events gemäß der Seite [Prüfung eines Security-Event-Token (SET)](../getting-started/event-log/set-validation.mdx). @@ -119,10 +119,12 @@ Die UUIDs der Anlagen in der Submission müssen den Schlüsseln der Anlagen in d ``` ## Überprüfung des Metadatensatzes +Nach der Prüfung des Ereignisprotokolls muss der vom sendenden System erzeugte Metadatensatz (submission/encryptedMetadata) geprüft werden. +Dazu MÜSSEN nach der Entschlüsselung des Metadatensatzes die folgenden Prüfungen durchgeführt werden: ### Authentication-Tag prüfen -Stimmt der Authentication-Tag des Metadatensatzes (submission/encryptedMetadata) mit dem im Submit-Submission-Event (authenticationTags/metadata) überein? +Stimmt der Authentication-Tag des verschlüsselten Metadatensatzes mit dem im Submit-Submission-Event (authenticationTags/metadata) überein? ```json { @@ -135,7 +137,7 @@ Stimmt der Authentication-Tag des Metadatensatzes (submission/encryptedMetadata) ### Entschlüsselung -Kann der Metadatensatz (submission/encryptedMetadata) entschlüsselt werden? +Kann der Metadatensatz entschlüsselt werden? ```json { @@ -212,6 +214,154 @@ Ist der Metadatensatz valide bezüglich des verwendeten Metadatenschemas? } ``` +### Sicherstellen der Integrität einer Submission {#integrity} +<!-- Allgemeine Beschreibung für Sender + Subscriber --> +Es muss sichergestellt sein, dass Zwischensysteme, wie z. B. auch FIT-Connect selbst, Fachdaten oder Anhänge von Submissions nicht austauschen können. +Hierfür wird eine Hashfunktion verwendet, welche die Integrität der Datensätze prüfbar macht. +Die so berechneten Hashes werden vom sendenden System in den Metadaten verschlüsselt abgelegt und können bei Abruf vom empfangenden System validiert werden. + +Nur wenn sowohl der Sender als auch der Subscriber Ihre Aufgaben übernehmen, ist die Integrität einer Submission sichergestellt. +Wie diese Aufgaben für den Subscriber im Detail aussehen, wird im Folgenden beschrieben. +Eine Beschreibung der Aufgaben des Senders findet sich im Artikel [Metadatensatz erstellen](../sending/metadata.mdx#integrity). + +#### Aufgaben des Subscribers + +<!-- Aufgaben des Subscribers --> +Nachdem ein Antrag empfangen wurde und **vor** dessen Weiterverwendung, muss die Integrität der Fachdaten und Anhänge sichergestellt werden. +Starten wir mit den **Fachdaten**: + +1. Prüfen, ob **Fachdaten** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. +2. Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512) der **entschlüsselten** Fachdaten. +3. Prüfen, ob dieser Hash mit dem aus den Metadaten übereinstimmt (Feld `.data.hash.content`). + + a. Wenn ja: Die Integrität der Fachdaten ist sichergestellt. + b. Wenn nein: Die Integrität der Fachdaten ist nicht gestellt. Die Fachdaten wurden durch ein Zwischensystem verändert! + +<!-- TODO: Beschreibung, was im Fall einer Integritätsverletzung getan werden sollte. --> + +Nun zu den **Anhängen**: + +1. Prüfen, ob **Anhänge** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. +2. Für jeden Anhang: Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512) der **entschlüsselten** Anhänge. +3. Für jeden Anhang: Prüfen, ob dieser Hash mit dem aus den Metadaten übereinstimmt (Feld `.attachments.*.hash.content`). + + a. Wenn ja: Die Integrität des Anhangs ist sichergestellt. + b. Wenn nein: Die Integrität des Anhangs ist nicht gestellt. Der Anhang wurden durch ein Zwischensystem verändert! + +<!-- TODO: Beschreibung, was im Fall einer Integritätsverletzung getan werden sollte. --> + +<Tabs + defaultValue="java" + groupId="code-examples" + values={[ + { label: 'CLI', value: 'cli', }, + { label: 'Java', value: 'java', }, + { label: 'Python', value: 'python', }, + { label: '.NET', value: 'dotnet', }, + ] +}> + <TabItem value="cli"> + + ```bash + ➜ HASH="92aae16fa71f045b482dafdfa12aed8dc502945444367e78600bb48df32d2b4be01e805c923cc8de11992616666cc80e9e133b73b1f234f8a27688a61ab065a9" + + # Erfolgreiche Hashvalidierung. Integrität der Fachdaten sichergestellt. + ➜ echo "$HASH fachdaten.json" | sha512sum --check + fachdaten.json: OK + + # Fehlgeschlagene Hashvalidierung. Integrität der Fachdaten fehlerhaft. + # Der Hash wurde manuell modifiziert (und dadurch ungültig gemacht). + ➜ INVALID_HASH=00000000001f045b482dafdfa12aed8dc502945444367e78600bb48df32d2b4be01e805c923cc8de11992616666cc80e9e133b73b1f234f8a27688a61ab065a8 + ➜ echo "$INVALID_HASH fachdaten.json" | sha512sum --check + fachdaten.json: FAILED + sha512sum: WARNING: 1 computed checksum did NOT match + ``` + + </TabItem> + + <TabItem value="java"> + + Der vollständige Beispielcode kann [im Beispielcoderepository unter `/java/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/java/metadata-verifier) + gefunden werden. + + ```java + MetadataVerifier metadataVerifier = new MetadataVerifier(); + + byte[] exampleFileContent = MetadataVerifier.class.getResourceAsStream("/example.pdf").readAllBytes(); + + // Subscriber: verify Hash of data (Fachdaten) or attachments (Anhänge) + String hashFromSender = "bf85bd96831e5df2200b76a8c7e3c74044e96bc30d1ffc3d1c4b05d4ee5b258714ab28a4ee12c9eb7f7cec1878d49036f4ccaf809a6c9545707fb1b91f2676ae"; + boolean verify = metadataVerifier.verify(metadataVerifier.fromHexString(hashFromSender), exampleFileContent); + System.out.printf("Subscriber: Verification %s\n", verify ? "OK" : "FAILED"); + ``` + + </TabItem> + <TabItem value="python"> + + Der vollständige Beispielcode kann [im Beispielcoderepository unter `/python/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/python/metadata-verifier) + gefunden werden. + + ```python + import hashlib + import json + + def create_hash(data: bytes): + return hashlib.sha512(data) + + def verify_hash(original_hash: bytes, data: bytes) -> bool: + new_hash = create_hash(data).digest() + return original_hash == new_hash + + hash_from_sender = "bf85bd96831e5df2200b76a8c7e3c74044e96bc30d1ffc3d1c4b05d4ee5b258714ab28a4ee12c9eb7f7cec1878d49036f4ccaf809a6c9545707fb1b91f2676ae" + with open(example_pdf, "rb") as data_from_sender: + data_from_sender_bytes = data_from_sender.read() + + verify_ok = verify_hash(bytes.fromhex(hash_from_sender), data_from_sender_bytes) + print(f"Subscriber: Verification {'OK' if verify_ok else 'FAILED'}") + ``` + + </TabItem> + <TabItem value="dotnet"> + + Der vollständige Beispielcode kann [im Beispielcoderepository unter `/dotnet/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/dotnet/metadata-verifier) + gefunden werden. + + ```csharp + using System; + using System.Security.Cryptography; + using System.Reflection; + + string hashFromSender = "bf85bd96831e5df2200b76a8c7e3c74044e96bc30d1ffc3d1c4b05d4ee5b258714ab28a4ee12c9eb7f7cec1878d49036f4ccaf809a6c9545707fb1b91f2676ae"; + + using (Stream? inputData = Assembly.GetExecutingAssembly().GetManifestResourceStream("example.pdf")) + { + if (inputData == null) + { + Console.Error.WriteLine("Error reading file from assembly."); + return; + } + using (var hashFunction = SHA512.Create()) + { + byte[] hash = hashFunction.ComputeHash(inputData); + byte[] comparisonHash = Convert.FromHexString(hashFromSender); + + Console.Write("Subscriber: Verification "); + if (hash.SequenceEqual(comparisonHash)) + { + Console.WriteLine("OK"); + } + else + { + Console.WriteLine("FAILED"); + } + } + + } + ``` + + </TabItem> +</Tabs> + ### Verwaltungsleistung abgleichen (I) Stimmt der Identifier des Metadatensatzes `publicServiceType/identifier` diff --git a/docs/sending/metadata.mdx b/docs/sending/metadata.mdx new file mode 100644 index 0000000000000000000000000000000000000000..82cb30061a6a6d74cdd60af21504d75f25039201 --- /dev/null +++ b/docs/sending/metadata.mdx @@ -0,0 +1,134 @@ +--- +title: Metadatensatz erstellen +--- + +Für jede Einreichung müssen sendende Systeme einen Metadatensatz erstellen und beim [Versenden der Einreichung](submit.mdx) an FIT-Connect übermitteln. +Der Metadatensatz wird dabei wie auch die Fachdaten Ende-zu-Ende-verschlüsselt, sodass FIT-Connect keinen Einblick in die enthaltenen Metadaten erhält. + +Im Abschnitt `contentStructure` des Metadatensatzes einer Einreichung wird die Struktur der Einreichung und deren Inhalte, wie Anhänge oder Fachdaten, beschrieben. +Der Metadatensatz enthält ebenfalls Hashwerte der übermittelten Fachdaten und Anlagen, um einen bösartigen Austausch von einzelnen Anlagen zu verhindern (siehe unten). +Zusätzlich können weitere Informationen über Verwaltungskund:innen hinterlegt werden. +Weitere Informationen finden sich im [Grundlagen-Artikel zum Metadatensatz](../getting-started/submission/metadata.mdx). +Eine genaue Definition und weitere Informationen sind in der [Schema-Beschreibung zum Metadatensatz](../metadata/overview.mdx) zu finden. + +## Sicherstellen der Integrität einer Submission {#integrity} +<!-- Allgemeine Beschreibung für Sender + Subscriber --> +Es muss sichergestellt sein, dass Zwischensysteme, wie z. B. auch FIT-Connect selbst, Fachdaten oder Anhänge von Submissions nicht austauschen können. +Hierfür wird eine Hashfunktion verwendet, welche die Integrität der Datensätze prüfbar macht. +Die so berechneten Hashes werden vom sendenden System in den Metadaten verschlüsselt abgelegt und können bei Abruf vom empfangenden System validiert werden. + +Nur wenn sowohl der Sender als auch der Subscriber Ihre Aufgaben übernehmen, ist die Integrität einer Submission sichergestellt. +Wie diese Aufgaben für den Sender im Detail aussehen, wird im Folgenden beschrieben. +Eine Beschreibung der Aufgaben des Subscribers findet sich im Artikel [Einreichung überprüfen](../receiving/verification.mdx#integrity). + + +### Aufgaben des Senders +Vor dem Versenden des Antrags muss der Sender sowohl für die Fachdaten als auch für jeden einzelnen Anhang den Hashwert berechnen. +Starten wir mit den **Fachdaten**: + +1. Prüfen, ob **Fachdaten** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. +2. Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512) der **unverschlüsselten** Fachdaten. +3. Schreiben des Hashtyps sowie des Hashwertes in die Metadaten unter `.data.hash`. + +Nun zu den **Anhängen**: + +1. Prüfen, ob **Anhänge** vorhanden sind. Wenn nein, können die Schritte 2. und 3. übersprungen werden. +2. Für jeden Anhang: Berechnen eines mit dem Metadatenschema kompatiblen Hashes (aktuell: SHA-512) der **unverschlüsselten** Anhänge. +3. Für jeden Anhang: Schreiben des Hashtyps sowie des Hashwertes in die Metadaten unter `.attachments.*.hash`. + +<Tabs + defaultValue="java" + groupId="code-examples" + values={[ + { label: 'CLI', value: 'cli', }, + { label: 'Java', value: 'java', }, + { label: 'Python', value: 'python', }, + { label: '.NET', value: 'dotnet', }, + ] +}> + <TabItem value="cli"> + + ```bash + # Ohne Dateinamen am Ende + ➜ sha512sum fachdaten.json | cut -d' ' -f1 + 92aae16fa71f045b482dafdfa12aed8dc502945444367e78600bb48df32d2b4be01e805c923cc8de11992616666cc80e9e133b73b1f234f8a27688a61ab065a9 + ``` + </TabItem> + + <TabItem value="java"> + + Der vollständige Beispielcode kann [im Beispielcoderepository unter `/java/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/java/metadata-verifier) + gefunden werden. + + ```java + MetadataVerifier metadataVerifier = new MetadataVerifier(); + + byte[] exampleFileContent = MetadataVerifier.class.getResourceAsStream("/example.pdf").readAllBytes(); + + // Sender: create hash of data (Fachdaten) or attachments (Anhänge) for Metadata + byte[] hash = metadataVerifier.createHash(exampleFileContent); + String hexHash = MetadataVerifier.toHexString(hash); // Optional + System.out.printf("Sender: {\"type\": \"sha512\", \"content\": \"%s\"}\n", hexHash); + ``` + + </TabItem> + <TabItem value="python"> + + Der vollständige Beispielcode kann [im Beispielcoderepository unter `/python/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/python/metadata-verifier) + gefunden werden. + + ```python + import hashlib + import json + + def create_hash(data: bytes): + return hashlib.sha512(data) + + def sender(example_pdf): + with open(example_pdf, "rb") as file_to_send: + file_to_send_bytes = file_to_send.read() + file_to_send_hash = create_hash(file_to_send_bytes) + print( + json.dumps( + {"type": "sha512", "content": file_to_send_hash.hexdigest()}, indent=4 + ) + ) + ``` + + </TabItem> + <TabItem value="dotnet"> + + Der vollständige Beispielcode kann [im Beispielcoderepository unter `/dotnet/metadata-verifier`](https://git.fitko.de/fit-connect/fit-connect-tools/-/tree/main/dotnet/metadata-verifier) + gefunden werden. + + ```csharp + using System; + using System.Security.Cryptography; + using System.Reflection; + using System.Text.Json; + + using (Stream? inputData = Assembly.GetExecutingAssembly().GetManifestResourceStream("example.pdf")) + { + if (inputData == null) + { + Console.Error.WriteLine("Error reading file from assembly."); + return; + } + using (var hashFunction = SHA512.Create()) + { + byte[] hash = hashFunction.ComputeHash(inputData); + String hashAsString = BitConverter.ToString(hash) + .Replace("-", "") + .ToLowerInvariant(); + + Console.WriteLine("Sender: " + JsonSerializer.Serialize(new + { + type = "sha512", + content = hashAsString + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + ``` + + </TabItem> +</Tabs> diff --git a/sidebar.js b/sidebar.js index f8007f74f2a2147c38a68b6b74506e3719bbcda2..e92ee8475667fb11188db59c480b106cac76df90 100644 --- a/sidebar.js +++ b/sidebar.js @@ -50,6 +50,7 @@ module.exports = { items: [ 'sending/overview', 'sending/start-submission', + 'sending/metadata', 'sending/encrypt', 'sending/attachments', 'sending/submit',