Zum Hauptinhalt springen

Datensicherheit

Dr.wait verwendet drei Prinzipien, um einen klaren Umgang mit Daten im digitalen Wartezimmer zu ermöglichen. Zusätzlich zur Datensparsamkeit, Datenkurzlebigkeit und Transparenz, schafft Dr.wait eine zusätzliche Ebene an Sicherheit mit einer Ende-zu-Ende-Verschlüsselung der persönlichen Daten. So funktioniert die Verschlüsselung im Detail:

Asymmetrische Verschlüsselung#

Ein asymmetrisches Verschlüsselungsverfahren bedeutet im Wesentlichen, dass mit zwei Schlüsseln gearbeitet wird: Ein öffentlicher Schlüssel, um Daten zu verschlüsseln und ein privater Schlüssel, um die verschlüsselten Daten wieder zu entschlüsseln. Ein öffentlicher Schlüssel kann z.B. so aussehen:

-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs0m0fODsKjU/LRzRc1ToWIsxBSfhplEMptf7uSBpUd8Mxtr65Mdtp/Bn1a7M9XoSZ34K0nALFkFSn5T6Vqj3bpJ2aX3hkk55OhHFo1lFge5hKqwd8PEZUs8aTUuPgZLnMO81MrRV5Msua6/0oRBRtXlGRauLprewKMneg51kM3U/D4W7Aq8kmLY+n3fJPHwXLOfuKs06Ze7F+WNwBzcTomDrzpPDhoUMwhvFwDvveS93W0pD7FfudjgNV5olp3q9KWc6OBbPAs2lqja7ZfOoHkr93F5sNWMhBJDomGHvQtw72cMgKHXBdLoE31t1J4pWpmWzylTyFcbZuz83YjJsllf4rETxaRlr9N6EDnF69PLa2KRCiYF9mvUfMXfRQy30GvaP8f+qah5Vdz3H5kxr2Mwk4NUEdHGbkXwwfpki7kjTy2RvITbj8qsP61v6UMdenGdBLCjzIUI1cCHO2qLswA1XI4VbLAXZQTCKiywE6/kcOdS6alyWqUUVz2NKZNQeVafa31zUdKUIKdDAUYEIluvFyJcoqSpl8gCRz4KbOna9m5HnkUO1ozlJgbMRcwsiBuZnut5O3sECdh54qXveWLdrPxU20j32ZYOy9gz3iWjO3WN7BEG9X+z8Ec34pbtAaZ1gqd+eRCNZjirZYbwn7JgdbPRRQIZfevXNujoqGPMCAwEAAQ==-----END PUBLIC KEY-----

Als Gegenstück zum öffentlichen Schlüssel kann der private Schlüssel so aussehen:

-----BEGIN PRIVATE KEY-----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-----END PRIVATE KEY-----

Das Schlüsselpaar wird nach der erstmaligen Einrichtung auf dem Rechner der Arztpraxis generiert:

const keyPair = await window.crypto.subtle.generateKey(  {    name: "RSA-OAEP",    modulusLength: 4096,    publicExponent: new Uint8Array([1, 0, 1]),    hash: "SHA-256",  },  true,  ["encrypt", "decrypt"])

Key-Wrapping#

Um den privaten Schlüssel nicht in Klartext in der Datenbank zu speichern, passiert noch ein wichtiger Schritt: Der private Schlüssel wird mit einem zusätzlichen geheimen Key ummantelt und encodiert. Dieser zusätzlicher Schlüssel wird aus einem - nur der Praxis bekannten - Passwort abgeleitet:

const wrapCryptoKey = async (keyToWrap, password) => {  const salt = window.crypto.getRandomValues(new Uint8Array(16))  const ivWrap = window.crypto.getRandomValues(new Uint8Array(12))  const { iv, wrappingKey } = await getKey(salt, password)
  const exportablePrivateKey = await window.crypto.subtle.wrapKey(    "jwk",    keyToWrap,    wrappingKey,    {      name: "AES-GCM",      iv: ivWrap,    }  )
  return { exportablePrivateKey, iv, ivWrap, salt }}const getKey = async (salt, password) => {  const enc = new TextEncoder()  const keyMaterial = await window.crypto.subtle.importKey(    "raw",    enc.encode(password),    { name: "PBKDF2" },    false,    ["deriveBits", "deriveKey"]  )  const iv = window.crypto.getRandomValues(new Uint8Array(12))
  const key = await window.crypto.subtle.deriveKey(    {      name: "PBKDF2",      salt: salt,      iterations: 100000,      hash: "SHA-256",    },    keyMaterial,    {      name: "AES-GCM",      iv: iv,      length: 256,    },    true,    ["wrapKey", "unwrapKey"]  )  return { wrappingKey: key, iv, salt }}

Der private Schlüssel, ummantelt mit dem Passwort, wird nun für die Praxis in der Datenbank gespeichert und kann von allen Praxismitarbeitern aufgerufen werden.

Wie werden die Daten jetzt verschlüsselt?#

Zurück zu den Daten. Bei Dr.wait werden die Patientendaten also mit dem öffentlichen Schüssel der Praxis bereits auf dem Smartphone in der Patienten-App verschlüsselt. Das sieht ungefähr so aus:

const encryptData = async (str, publicKey) => {  let enc = new TextEncoder()  const encoded = enc.encode(str)  const encrypted = await window.crypto.subtle.encrypt(    {      name: "RSA-OAEP",      hash: "SHA-256",    },    publicKey,    encoded  )
  return btoa(String.fromCharCode(...new Uint8Array(encrypted)))}
const publicKey = "-----BEGIN PUBLIC KEY-----..." // See above for full public key.const encryptedName = encryptData("Joe Duncan", publicKey)

Nach dem erfolgreichen Verschlüsseln werden die Patientendaten aus der App zu den Servern von Dr.wait geschickt und in der Datenbank gespeichert.

Auf den Computern der Praxis werden nach erfolgreicher Authentifizierung der Praxismitarbeiter, die gesamte Warteschlange samt verschlüsselter Daten geladen. Um die Daten zu entschlüsseln, wird der private Schlüssel (mit einem Passwort ummantelt) aus der Datenbank geladen und nach Eingabe des Passworts durch die Praxis dekodiert.

Die Ebenen der Sicherheit#

Das asymmetrische Verschlüsselungsverfahren schafft im Zusammenspiel mit Key-Wrapping eine gute zusätzliche Ebene an Datensicherheit. Das hilft natürlich auch nur, wenn die Sicherheit in anderen Bereichen wie Datenbankzugriff, Serververwaltung und Datenübertragung auch beachtet wird.