Skip to content

Commit

Permalink
Implement Feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
mfiebig committed Nov 15, 2024
1 parent b9acba1 commit e578759
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 15 deletions.
159 changes: 145 additions & 14 deletions concept/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,11 @@ <h1>Notification Management <span class="image right"><img src="../images/gemati
<li><a href="#_registrierung_einer_epa_fdv_instanz">Registrierung einer ePA-FdV-Instanz <span class="image"><img src="https://img.shields.io/badge/Status-In_Review-orange" alt="Status In Review orange"></span></a></li>
<li><a href="#_deregistrierung_einer_fdv_instanz">Deregistrierung einer FdV-Instanz <span class="image"><img src="https://img.shields.io/badge/Status-Draft-red" alt="Status Draft red"></span></a></li>
<li><a href="#_liste_aktuelle_pushers_enthalten">Liste aktuelle Pushers enthalten <span class="image"><img src="https://img.shields.io/badge/Status-Draft-red" alt="Status Draft red"></span></a></li>
<li><a href="#_versenden_von_push_notifications">Versenden von Push-Notifications <span class="image"><img src="https://img.shields.io/badge/Status-Draft-red" alt="Status Draft red"></span></a></li>
<li><a href="#_versenden_von_push_notifications">Versenden von Push-Notifications <span class="image"><img src="https://img.shields.io/badge/Status-Draft-red" alt="Status Draft red"></span></a>
<ul class="sectlevel3">
<li><a href="#_versenden_aus_push_gateway_sicht">Versenden aus Push Gateway Sicht <span class="image"><img src="https://img.shields.io/badge/Status-Work_In_Progress-red" alt="Status Work In Progress red"></span></a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_beispiele">Beispiele <span class="image"><img src="https://img.shields.io/badge/Status-Draft-red" alt="Status Draft red"></span></a>
Expand Down Expand Up @@ -546,32 +550,46 @@ <h3 id="_authentisierung">Authentisierung <span class="image"><img src="https://
<div class="sect2">
<h3 id="_verschlüsselung_des_benachrichtigungsinhaltes">Verschlüsselung des Benachrichtigungsinhaltes <span class="image"><img src="https://img.shields.io/badge/Status-Draft-red" alt="Status Draft red"></span></h3>
<div class="paragraph">
<p>Der Benachrichtigungsinhalt einer jeden Benachrichtigung wird mittels eines Authenticated-Encryption-Verfahrens verschlüsselt (AES/GCM), sodass der Inhalt der Benachrichtigung nicht von Dritten eingesehen oder veränderten werden kann.
Wenn sich eine E-Rezept-FdV-Installation beim E-Rezept-Fachdienst für Benachrichtigungen registriert (vgl. Abschnitt 4.6.1), erzeugt die App ein initiales gemeinsames Geheimnis (<code>initial-shared-secret</code> (<code>ISS</code>)) und überträgt dieses kryptographisch gesichert an den E-Rezept-Fachdienst.
Dieses gemeinsame Geheimnis ist die Grundlage der kryptographischen Sicherung des Benachrichtigungsinhaltes. Die Benachrichtigung wird vom Notification Service mit verschlüsselten Benachrichtigungsinhalt über den Notification Provider an die E-Rezept-FdV-Installation übermittelt.
Ganz ähnlich wie bei vielen Messaging-Anwendungen werden die verwendeten Schlüssel für die kryptographische Absicherung der Nachrichten regelmäßig gewechselt auf eine Weise, dass eine Wiederherstellbarkeit von alten Schlüssel kryptographisch ausgeschlossen ist.
Der Notification Service erhält ein ISS und einen Zeitstempel von dessen Erzeugung von dem E-Rezept-FdV bei der Registrierung. Mittels einer "Hashed Message Authentication Code (HMAC)-based key derivation function" (HKDF) [RFC-5869] werden per <code>HKDF(ISS, info="&lt;Jahr&gt;-&lt;Monat&gt;")</code> zwei Werte abgeleitet:</p>
<p>Der Benachrichtigungsinhalt einer jeden Benachrichtigung wird mittels eines Authenticated-Encryption-Verfahrens verschlüsselt (AES/GCM), sodass der Inhalt der Benachrichtigung nicht von Dritten eingesehen oder veränderten werden kann.</p>
</div>
<div class="ulist">
<ul>
<div class="paragraph">
<p>Wenn sich eine E-Rezept-FdV-Installation beim E-Rezept-Fachdienst für Benachrichtigungen registriert (vgl. Abschnitt 4.6.1), erzeugt die App ein initiales gemeinsames Geheimnis (<code>initial-shared-secret</code> (<code>ISS</code>)) und überträgt dieses kryptographisch gesichert an den E-Rezept-Fachdienst.</p>
</div>
<div class="paragraph">
<p>Dieses gemeinsame Geheimnis ist die Grundlage der kryptographischen Sicherung des Benachrichtigungsinhaltes. Die Benachrichtigung wird vom Notification Service mit verschlüsselten Benachrichtigungsinhalt über den Notification Provider an die E-Rezept-FdV-Installation übermittelt.</p>
</div>
<div class="paragraph">
<p>Ganz ähnlich wie bei vielen Messaging-Anwendungen werden die verwendeten Schlüssel für die kryptographische Absicherung der Nachrichten regelmäßig gewechselt auf eine Weise, dass eine Wiederherstellbarkeit von alten Schlüssel kryptographisch ausgeschlossen ist.</p>
</div>
<div class="paragraph">
<p>Der Notification Service erhält ein ISS und einen Zeitstempel von dessen Erzeugung von dem E-Rezept-FdV bei der Registrierung. Mittels einer "Hashed Message Authentication Code (HMAC)-based key derivation function" (HKDF) [RFC-5869] werden per <code>HKDF(ISS, info="&lt;Jahr&gt;-&lt;Monat&gt;")</code> zwei Werte abgeleitet:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Ein Geheimnis für den Monat und Jahr des Zeitstempels (<code>shared-secret-Jahr-Monat</code>)</p>
</li>
<li>
<p>ein AES/GCM-Schlüssel für den Monat und Jahr des Zeitstempels (<code>AES/GCM-Schlüssel-Jahr-Monat</code>).</p>
</li>
</ul>
</ol>
</div>
<div class="paragraph">
<p>Diese beiden Werte werden im Notification Service sicher gespeichert und das ISS wird im Notification Service gelöscht.</p>
</div>
<div class="sect3">
<h4 id="_beispiel_für_einen_austausch_im_oktober_2023">Beispiel für einen Austausch im Oktober 2023: <span class="image"><img src="https://img.shields.io/badge/Status-In_Review-orange" alt="Status In Review orange"></span></h4>
<div class="paragraph">
<p>Das ISS sei zufällig erzeugt gleich (hexdump) <code>f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2</code>. Dann ergibt <code>HKDF(ISS, info="2023-10", L=64) = (hexdump) 185fed66ea5cabbe00147bbd298b5dab0ed41b57ab254d35897b3a4504306e3b3b4adcd58dea98db8e9cb0f5763fcd04fe932d67926cc04b20ba2a2f304ffff9</code>. Die ersten 32 Byte (256 Bit) sind das <code>shared-secret-2023-10</code> gleich (hexdump) <code>185fed66ea5cabbe00147bbd298b5dab0ed41b57ab254d35897b3a4504306e3b</code> und die letzten 32 Byte sind der <code>AES/GCM-Schlüssel-2023-10</code> ist gleich (hexdump) <code>3b4adcd58dea98db8e9cb0f5763fcd04fe932d67926cc04b20ba2a2f304ffff9</code>.
Soll im Oktober 2023 eine Benachrichtigung kryptographisch gesichert werden, um sie an das E-Rezept-FdV zu versenden, dann wird der Schlüssel <code>AES/GCM-Key-2023-10</code> dafür verwendet. Soll im November 2023 eine Benachrichtigung gesichert werden, so muss per <code>HKDF(shared-secret-2023-10, info="2023-11")</code> wieder ein Geheimnis&#8201;&#8212;&#8201;diesmal für November 2023&#8201;&#8212;&#8201;und ein neuer AES/GCM-Schlüssel abgeleitet werden. <code>shared-secret-2023-11 = (hexdump) 0c8662d90b04818afb317406fe7fcfcf8d103cd9bc6ad7847890d28620e85ec3</code>, <code>AES/GCM-Schlüssel-2023-11 = (hexdump) 39aa5dacd538f53f4b956d84c9b8f2e26933274d160b9fd1a263a27681c6331b</code>
Alle <code>shared-secret-Jahr-Monat</code> und alle AES/GCM-Schlüssel-Jahr-Monat, die älter sind als zwei Monate werden, sowohl im Notification Service als auch im E-Rezept-FdV gelöscht, jedoch niemals das jüngste noch verfügbare (auch wenn es älter als zwei Monate ist). Der fachliche Hintergrund von "zwei Monaten" ist, dass sichergestellt sein muss, dass falls der E-Rezept-FD die Benachrichtigung Sekunden vor Monatsende erstellt, und diese im E-Rezept-FdV erst nach einigen Sekunden dann im Folgemonat empfangen werden, die Entschlüsselung im E-Rezept-FdV immer noch möglich sein muss.
Sollte erst im Januar 2024 die nächste Benachrichtigung gesendet werden, so muss die Ableitung für <code>2023-12</code> erzeugt werden und darauf basierend anschließend die Ableitung für <code>2024-01</code>. Anschließend werden die Ableitungs- und Schlüsseldaten für <code>2023-11`</code> gelöscht. Die Schlüsseldaten für <code>2024-01</code> werden für die kryptographische Sicherung verwendet.</p>
<p>Das ISS sei zufällig erzeugt gleich (hexdump) <code>f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2</code>. Dann ergibt <code>HKDF(ISS, info="2023-10", L=64) = (hexdump) 185fed66ea5cabbe00147bbd298b5dab0ed41b57ab254d35897b3a4504306e3b3b4adcd58dea98db8e9cb0f5763fcd04fe932d67926cc04b20ba2a2f304ffff9</code>. Die ersten 32 Byte (256 Bit) sind das <code>shared-secret-2023-10</code> gleich (hexdump) <code>185fed66ea5cabbe00147bbd298b5dab0ed41b57ab254d35897b3a4504306e3b</code> und die letzten 32 Byte sind der <code>AES/GCM-Schlüssel-2023-10</code> ist gleich (hexdump) <code>3b4adcd58dea98db8e9cb0f5763fcd04fe932d67926cc04b20ba2a2f304ffff9</code>.</p>
</div>
<div class="paragraph">
<p>Soll im Oktober 2023 eine Benachrichtigung kryptographisch gesichert werden, um sie an das E-Rezept-FdV zu versenden, dann wird der Schlüssel <code>AES/GCM-Key-2023-10</code> dafür verwendet. Soll im November 2023 eine Benachrichtigung gesichert werden, so muss per <code>HKDF(shared-secret-2023-10, info="2023-11")</code> wieder ein Geheimnis&#8201;&#8212;&#8201;diesmal für November 2023&#8201;&#8212;&#8201;und ein neuer AES/GCM-Schlüssel abgeleitet werden. <code>shared-secret-2023-11 = (hexdump) 0c8662d90b04818afb317406fe7fcfcf8d103cd9bc6ad7847890d28620e85ec3</code>, <code>AES/GCM-Schlüssel-2023-11 = (hexdump) 39aa5dacd538f53f4b956d84c9b8f2e26933274d160b9fd1a263a27681c6331b</code></p>
</div>
<div class="paragraph">
<p>Alle <code>shared-secret-Jahr-Monat</code> und alle AES/GCM-Schlüssel-Jahr-Monat, die älter sind als zwei Monate werden, sowohl im Notification Service als auch im E-Rezept-FdV gelöscht, jedoch niemals das jüngste noch verfügbare (auch wenn es älter als zwei Monate ist). Der fachliche Hintergrund von "zwei Monaten" ist, dass sichergestellt sein muss, dass falls der E-Rezept-FD die Benachrichtigung Sekunden vor Monatsende erstellt, und diese im E-Rezept-FdV erst nach einigen Sekunden dann im Folgemonat empfangen werden, die Entschlüsselung im E-Rezept-FdV immer noch möglich sein muss.</p>
</div>
<div class="paragraph">
<p>Sollte erst im Januar 2024 die nächste Benachrichtigung gesendet werden, so muss die Ableitung für <code>2023-12</code> erzeugt werden und darauf basierend anschließend die Ableitung für <code>2024-01</code>. Anschließend werden die Ableitungs- und Schlüsseldaten für <code>2023-11`</code> gelöscht. Die Schlüsseldaten für <code>2024-01</code> werden für die kryptographische Sicherung verwendet.</p>
</div>
<div class="paragraph">
<p>Somit erreicht man das Ziel, dass bei Kompromittierung eines <code>AES/GCM-Jahr-Monat-Schlüssels</code> nicht mehr Benachrichtigungen entschlüsselt werden können, die älter als zwei Monate sind.</p>
Expand Down Expand Up @@ -673,6 +691,119 @@ <h3 id="_versenden_von_push_notifications">Versenden von Push-Notifications <spa
</div>
<div class="title">Abbildung 4. Push-Notification-Versand</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Der Fachdienst führt folgende Schritte durch</p>
<div class="olist loweralpha">
<ol class="loweralpha">
<li>
<p>Erzeugen des Nachrichteninhalts für dieses spezifisches Ereignis. Die Strukturierung ist fachdienstspezifisch.</p>
</li>
<li>
<p>Erzeugen eines neuen gültigen Schlüssels, wenn kein gültiger vorhanden ist.</p>
</li>
</ol>
</div>
</li>
<li>
<p>Für jeden registrierten Pusher <code>p</code>, der für das Ereignis abonniert ist, wird eine Push-Benachrichtigung <code>Notification_p</code> mit mindestens folgenden Inhalten erzeugt (Die möglichen Felder und deren Beschreibungen sind auf der OpenAPI-Seite zu finden):</p>
<div class="olist loweralpha">
<ol class="loweralpha">
<li>
<p><code>ciphertext</code> = Nachrichteninhalt aus 1b, verschlüsselt mit dem aktuell gültigen Schlüssel.</p>
</li>
<li>
<p><code>time_message_encrypted</code> = Zeitpunkt der Verschlüsselung des Nachrichteinhaltes.</p>
</li>
<li>
<p><code>devices</code> = (mindestens: app_id, push_token)</p>
</li>
</ol>
</div>
</li>
<li>
<p>Für jeden Pusher p wird die Push-Benachrichtigung <code>Notification_p</code> an das Push Gateways des Pushers <code>p</code> übermittelt.</p>
</li>
<li>
<p>Das Push Gateway übermittelt die Push-Benachrichtigung <code>Notification_p</code> an den Push Provider.</p>
</li>
<li>
<p>Der Push-Provider sendet die Notification an die zur <code>push_token</code> gehörende FdV-Instanz.</p>
</li>
<li>
<p>Die FdV-Instanz entschlüsselt den Nachrichteninhalt mit dem aktuell gültigen Schlüssel (erzeugt ihn, wenn er nicht schon vorhanden ist) und zeigt dem Nutzer den Nachrichteninhalt entsprechend an.</p>
</li>
<li>
<p>Bei Bedarf kann sich der Nutzer anmelden, um sich beispielsweise ein eingestelltes Dokument anzusehen.</p>
</li>
</ol>
</div>
<div class="sect3">
<h4 id="_versenden_aus_push_gateway_sicht">Versenden aus Push Gateway Sicht <span class="image"><img src="https://img.shields.io/badge/Status-Work_In_Progress-red" alt="Status Work In Progress red"></span></h4>
<div class="sect4">
<h5 id="_apple">Apple</h5>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">HTTP-Header</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Wert</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Beschreibung</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>:method</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>POST</code></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>:path</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>/3/device/<strong>&lt;device_token&gt;</strong></code></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">authorization</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code><strong>&lt;provider_token&gt;</strong></code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Required for token-based authentication</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apns-push-type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>alert</code></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apns-id</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apns-expiration</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apns-priority</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apns-topic</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apns-collapse-id</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -793,7 +924,7 @@ <h5 id="_out">OUT</h5>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2024-11-14 15:24:48 +0100
Last updated 2024-11-15 11:21:38 +0100
</div>
</div>
</body>
Expand Down
46 changes: 45 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,58 @@
<img src="images/gematik_logo.png" alt="Gematik Logo">
</div>
</div>
<iframe id="content" name="content" src="" frameborder="0"></iframe>
<iframe id="content" name="content" src="concept/index.html" frameborder="0"></iframe>

<script>
function loadPage(element) {
var links = document.querySelectorAll('#menu a');
links.forEach(link => link.classList.remove('active'));
element.classList.add('active');
}

window.addEventListener('load', function() {
if (window.location.hash && window.location.hash.length > 2) {
var hash = window.location.hash.substring(2).replace('%23', '#');
document.getElementById('content').src = hash;
var links = document.querySelectorAll('#menu a');
links.forEach(link => {
if (hash.startsWith(link.getAttribute('href'))) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
}
});

document.getElementById('content').addEventListener('load', function() {
this.contentWindow.addEventListener('hashchange', function() {
console.log("hashchange" + this.location.pathname + this.location.hash);

let path = this.location.pathname + this.location.hash
// escape # from path
path = path.replace('#', '%23');

if (window.location.hash.substring(1) != path) {
window.location.replace("#" + path);
}
});
});

window.addEventListener('hashchange', function() {
if (window.location.hash && window.location.hash.length > 2) {
var hash = window.location.hash.substring(2).replace('%23', '#');
document.getElementById('content').src = hash;
var links = document.querySelectorAll('#menu a');
links.forEach(link => {
if (hash.startsWith(link.getAttribute('href'))) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
}
});
</script>
</body>
</html>

0 comments on commit e578759

Please sign in to comment.