KAPITEL 7

Encrypted Computation

Encrypted Computation ist ein Teilgebiet der Kryptografie, mit der Berechnungen auf Basis verschlüsselter Daten durchgeführt werden können, ohne diese dabei entschlüsseln zu müssen. Dieser Bereich wurde erstmals in den 1970er-Jahren wissenschaftlich erforscht und hat sich seitdem weiterentwickelt. Encrypted Computation bietet die Möglichkeit, auch unter unsicheren Bedingungen sichere Berechnungen durchzuführen. In diesem Kapitel werden Sie einige grundlegende Konzepte der Encrypted Computation kennenlernen und erfahren, wie Sie feststellen können, ob und wann diese Technologie eine gute Lösung für Ihre datenwissenschaftlichen Anforderungen darstellt.

Was genau ist Encrypted Computation?

Die Vorstellung, Berechnungen mit Daten durchzuführen, ohne sie dabei entschlüsseln zu müssen, scheint auf den ersten Blick unmöglich. Tatsächlich ist es aber möglich, Berechnungen mit Daten durchzuführen, ohne sie dabei zu entschlüsseln. Im Grunde gibt es zahlreiche Protokolle und Methoden, mit denen Berechnungen mit verschlüsselten Daten durchgeführt werden können. Von einigen haben Sie vielleicht schon gehört: homomorphe Verschlüsselung (engl. Homomorphic Encryption, HE), Secure Multiparty Computation (SMPC bzw. MPC) – im Deutschen auch als sichere Mehrparteienberechnung bekannt –, Garbled Circuits oder verwandte Methoden wie Null-Wissen-Beweise (engl. Zero-Knowledge Proofs, ZK- Proofs).

Ein Großteil der Verfahren der Encrypted Computation ist auf bestimmte mathematische Eigenschaften angewiesen, damit die Korrektheit bei der Verarbeitung verschlüsselter Daten erhalten bleibt. Dieses Kapitel soll Ihnen eine grundlegende Einführung bieten, auf der Sie im Anschluss an dieses Buch weiter aufbauen können.

Kryptografische Protokolle werden zum Verschlüsseln, Übertragen, Berechnen und Entschlüsseln von Informationen verwendet. Ein Protokoll ist ein Plan, der den Austausch von Informationen – in der Regel zwischen mehreren Computern bzw. Parteien – ermöglicht, um gemeinsam zu kommunizieren oder gemeinsam Berechnungen vorzunehmen. Wenn Sie im Internet surfen, verwenden Sie mehrere Verschlüsselungsund Netzwerkprotokolle gleichzeitig, wie etwa TLS, DNS und HTTPS.

image

Wenn Sie bereits Tools wie GitHub verwendet haben, denken Sie wahrscheinlich an Verschlüsselung im Sinne eines Public-Private-Key-Paars. Doch es gibt weitaus mehr Möglichkeiten der Verschlüsselung als nur diese! Beim Lesen dieses Kapitels sollten Sie nicht versuchen, diese Protokolle in einen bereits bekannten Kontext einzuordnen, da Ihr gedanklicher Ansatz wahrscheinlich nicht dazu passt. Machen Sie sich mit diesen Bausteinen vertraut und spielen Sie mit den Notebooks im Repository des Buchs herum, um so ein neues Verständnis zu entwickeln.

Encrypted Computation löst ein Sicherheitsproblem, wenn mehrere Parteien gemeinsam Berechnungen durchführen möchten, jedoch keine unverschlüsselten bzw. im Klartext vorliegenden Daten verwenden wollen. In solchen Fällen besteht ein unterschiedliches Maß an Vertrauen zwischen den beteiligten Parteien. Mit verschlüsselten Daten kann eine bessere Kontrolle über die Daten gewahrt und das Vertrauen erhöht werden, da kontrolliert werden kann, welche Daten entschlüsselt werden und von wem.

Ein klassisches Problem der Verschlüsselung ist das Millionärsproblem, das von Andrew Yao untersucht wurde (https://oreil.ly/47-jZ). Dabei geht es um zwei Millionäre, die herausfinden wollen, wer reicher ist, um zu bestimmen, wer die Rechnung beim Abendessen bezahlen muss. Beide wollen ihr Vermögen nicht verraten, würden aber gern in Erfahrung bringen, wer reicher ist. Yao gelang es, dieses Problem mithilfe einer frühen Implementierung von Verschlüsselungsprotokollen zu lösen, die Sie in diesem Kapitel kennenlernen werden (die Secure Multiparty Computation).

Encrypted Computation ist in einer Vielzahl von Fällen nützlich, in denen eine Entschlüsselung der Daten nicht erwünscht oder sogar nicht erlaubt ist. Sehen wir uns an, wann Encrypted Computation das Vertrauen und die Sicherheit erhöhen und neue Wege bei der Zusammenarbeit mit Daten eröffnen können.

Wann Encrypted Computation verwendet werden sollte

Encrypted Computation eignet sich hervorragend für den Einsatz in Fällen, in denen Sie den beteiligten Parteien oder dem gesamten Setting nicht vertrauen können:

Unsichere Cloud-Umgebungen

Angenommen, Sie möchten Berechnungen in einer Cloud-Umgebung durchführen und dabei lokale Daten nutzen. Sie haben jedoch Bedenken, dass die Cloud-Umgebung nicht sicher ist. Encrypted Computation kann sicherstellen, dass die Daten, die in der Cloud gespeichert sind, niemals entschlüsselt werden.

Berechnungen mit Dritten

Was ist, wenn Sie Berechnungen gemeinsam mit anderen durchführen möchten, aber nicht wollen, dass die anderen Beteiligten Ihre Rohdaten einsehen können? Encrypted Computation ermöglicht Ihnen, Berechnungen durchzuführen, ohne dass dabei die Daten im Klartext offengelegt werden. Zudem können Sie vor Beginn der Berechnungen festlegen, wer das Ergebnis sehen kann und wie es zugänglich gemacht werden soll. Dadurch werden alle Parteien vor Beginn der Berechnungen durch entsprechende Sicherheits- und Datenschutzmaßnahmen geschützt.

Berechnungen auf Basis verschlüsselter Daten

Unter Umständen werden Sie Berechnungen mit hochsensiblen Daten durchführen wollen, etwa im Rahmen einer Krebsdiagnose, wenn Sie ein Foto auswerten sollen, aber die Patientin gegebenenfalls nicht möchte, dass seine Daten offengelegt werden. Encrypted Computation bietet die Sicherheit und den Schutz der Privatsphäre, die von Nutzerinnen und Nutzern erwartet wird. Das Ergebnis wird auf Basis verschlüsselter Daten berechnet und dem Nutzer zurückgegeben, damit dieser es entschlüsseln kann.

Vergleich von Daten zwischen Parteien

In manchen Fällen möchten Sie sicherstellen, dass ein neues Geschäftsvorhaben für beide Seiten von Vorteil ist. Angenommen, Sie leiten eine Marketingabteilung und möchten wissen, ob ein bestimmter Dienst für Ihre Nutzer von Interesse ist, bevor Sie eine neue Zusammenarbeit eingehen. Was, wenn Sie vorher die Nutzerbasis vergleichen könnten, um zu sehen, wie viele Überschneidungen es bei den Nutzerinnen und Nutzern gibt? Mit Encrypted Computation können Datensätze zwischen Parteien verglichen werden, ohne dass dabei die Werte der beiden Datensätze als Klartext offengelegt werden. Dadurch wird der Schutz der Privatsphäre der Nutzer gewährleistet und die Zusammenarbeit gefördert.

Verteilen von Daten oder Secrets

Es gibt Situationen, in denen die Speicher- oder Rechenumgebung, in der Sie arbeiten, nicht vertrauenswürdig ist – oder Sie haben es sich vielleicht zur Aufgabe gemacht, eine Zero-Trust-Architektur auf die nächste Stufe zu bringen. Um solchen Situationen zu begegnen, können Sie Ihre Daten oder Secrets (bzw. Geheimnisse) verschlüsselt und dezentral speichern. Wenn sich jemand Zugang zu einem Teil der Daten verschafft, kann er sie nicht entschlüsseln oder verwenden, es sei denn, er erhält Zugang zu den anderen Teilen des Secrets bzw. der Daten. Dieser Gedanke spiegelt sich auch in Zero-Trust-Architekturen wider, bei denen die Funktionsweise von Zugangsdaten und einer sicheren Speicherung neu überdacht wird und diese Prüfungen und Kontrollen verteilt werden. Um ein konkretes Beispiel zu nennen: Unbound Security (https://oreil.ly/Z8hJP) hat verteilte Schlüssel verwaltet, um eine bessere Sicherheit für Kryptowährungs-Wallets und andere wertvolle Vermögenswerte zu bieten.1

Sicherstellung der Zusammenarbeit und Verteilung der Kontrolle

Encrypted Computation kann verwendet werden, um Algorithmen oder Modelle zu erstellen, bei denen mehrere Parteien erforderlich sind. Aufgrund der Funktionsweise der Protokolle kann die Berechnung nur dann erfolgreich ausgeführt werden, wenn ein bestimmter Beteiligungsgrad erreicht wird. Dieser Schwellenwert gewährleistet eine gewisse demokratische Kontrolle hinsichtlich der Ausführung durch eine kleine oder größere Gruppe von Parteien. Für bestimmte Berechnungen – wie z.B. Auktionen, Wahlen, Entscheidungen von Ausschüssen oder Communitys – spiegelt Encrypted Computation online wider, wie Vertrauen in der realen Welt funktioniert. Mit Encrypted Computation können Abstimmungen diskret durchgeführt werden, während gleichzeitig Anforderungen – wie das Erreichen eines Quorums – erfüllt werden müssen, bevor eine Abstimmung durchgeführt werden kann.

Haftung

Encrypted Computation trägt dazu bei, die Haftungsrisiken für Rechts- und Sicherheitsteams zu verringern, genauso wie Encryption at Rest (d.h. Verschlüsselung während der Speicherung) ein »bestmögliches Bemühen« um die Sicherheit der Daten beweist. Wenn Ihr Unternehmen verschlüsselte Daten im Rahmen des Zugriffs und der Verarbeitung auf Daten verwendet, die hohen Risiken unterliegen, unterstreicht dies gegenüber Audit- oder Aufsichtsbehörden, dass Sie das Risiko und die potenzielle Gefährdung verringern. Außerdem erfüllen Sie strengere interne Sicherheitsrichtlinien, was für die Sicherheitsteams attraktiv ist und die finanziellen Haftungsrisiken für das Unternehmen verringert.

Darüber hinaus gibt es noch zahlreiche weitere Einsatzmöglichkeiten für Encrypted Computation, wie z.B. beim privaten und sicheren Datenabgleich (Matching), der Inferenz (d.h. im Rahmen von Vorhersagen) und der Suche. Die angeführten Beispiele sollten genügen, damit Sie jetzt einen Eindruck von den alltäglicheren Anwendungen dieser Technologie haben. Der Einsatz von Encrypted Computation hat eine Reihe von Vorteilen, die ganz allgemein auf die grundlegenden Vorteile der Verschlüsselung zurückzuführen sind. Sie sorgt dafür, dass Daten sicher sind und geheim gehalten werden, und erlaubt es dennoch, aus Daten wichtige Erkenntnisse zu ziehen und sie für Analysen und als Grundlage für Entscheidungen zu nutzen.

Um beurteilen zu können, wann Sie Encrypted Computation verwenden sollten, müssen Sie zunächst einige Grundprinzipien der Verschlüsselung verstanden haben – einschließlich der Unterscheidung zwischen Datenschutz und Geheimhaltung und der Frage, wie ein Problem im Hinblick auf die Bestimmung des entsprechenden Gefährdungsgrads modelliert werden kann. Mit diesen Grundlagen werden Sie in der Lage sein, Encrypted Computation auf reale Probleme anzuwenden.

Unterschied zwischen Datenschutz und Geheimhaltung

In diesem Buch haben Sie strenge und wissenschaftliche Datenschutzdefinitionen vor dem Hintergrund der Garantien, die Differential Privacy geben kann, kennengelernt. Wenn Kryptografen von Datenschutz bzw. Privacy sprechen, meinen sie in der Regel Geheimhaltung (engl. Secrecy). Sehen wir uns die Unterschiede an, damit Sie beides bewerten können, wenn Sie darüber entscheiden, wie Sie Daten verarbeiten.

Privacy bzw. Datenschutz ist, wie Sie bereits erfahren haben, die Garantie dafür, dass Informationen über eine Person nicht ohne deren Zustimmung oder Wissen an Dritte weiter- bzw. preisgegeben werden. Wenn Sie also die Privatsphäre der Personen, die in den Daten enthalten sind, schützen wollen, müssen Sie sich zunächst darüber im Klaren darüber sein, wie Informationen an die Öffentlichkeit gelangen könnten, und die Handhabung dieser Informationen so anpassen, dass diese nicht an die Öffentlichkeit gelangen können (Catastrophic Leakage). Dabei sollten Sie auch den jeweiligen Kontext berücksichtigen, in dem die Daten zur Verfügung gestellt wurden, sowie den zu erwartenden und angestrebten Grad des Datenschutzes, der sich aus den entsprechenden Governance-Instrumenten wie z.B. Richtlinien und Einverständniserklärungen ergibt.

Im Bereich der Kryptografie ist Privacy (bzw. Datenschutz) die Fähigkeit, darüber zu bestimmen und garantieren zu können, welche Daten an wen weitergegeben werden. Anders als bei Differential Privacy gibt es keine Annahmen darüber, inwieweit diese Informationen preisgegeben werden, sobald sie offengelegt werden. Diese Eigenschaft wird auch als Geheimhaltung bezeichnet, da sie zum Ausdruck bringen soll, dass die Werte so lange geheim bleiben, solange sie verschlüsselt sind. Allerdings können, ähnlich wie bei Berechnungen mit sensiblen Werten, auch bei Berechnungen mit geheimen Werten private Informationen nach außen dringen. Solange die Daten verschlüsselt sind, sind sie auch privat, da die Informationen durch den Verschlüsselungsmechanismus geheim gehalten werden. Sobald das entschlüsselte Ergebnis einsehbar ist, ist dies allerdings nicht mehr der Fall.

In einer Umgebung, in der Vertrauen auf mehrere Parteien verteilt ist (Distributed Trust Setting), ist Ihnen möglicherweise nur die Geheimhaltung und nicht der Schutz der Privatsphäre wichtig. Wenn, wie zuvor in Kapitel 6 beschrieben, Berechnungen über mehrere Parteien hinweg koordiniert werden, möchten die Parteien das Ergebnis gegebenenfalls zwar ohne Rauschen erhalten, aber dennoch nicht, dass jemand die konkreten Inputdaten einsehen kann. Hier bietet die Verschlüsselung die gewünschten Vorteile (nämlich Genauigkeit) und Geheimhaltung für die beteiligten Parteien.

Wenn Sie Encrypted Computation verwenden, müssen Sie einige Entscheidungen hinsichtlich der Geheimhaltung und des Schutzes der Privatsphäre treffen. Insbesondere die Entscheidung, wann Sie Daten verschlüsseln und entschlüsseln, ist wichtig, da dies für die Geheimhaltung bei der Encrypted Computation ausschlaggebend ist und davon abhängt, wer die Ergebnisse einsehen kann. Aber es gilt auch Garantien zum Schutz der Privatsphäre zu berücksichtigen. Das könnte beispielsweise bedeuten, dass Sie Differential Privacy anwenden, bevor Sie das Endergebnis offenlegen – oder auch zu einem bestimmten Zeitpunkt während des Rechenvorgangs. Wenn es Ihnen in erster Linie um die Geheimhaltung, nicht aber um den Schutz der Privatsphäre geht, sollte Encrypted Computation selbst die von Ihnen gewünschten Garantien bieten.

Threat Modeling

Um zu bestimmen, wann, wo und wie Sie Encrypted Computation einsetzen, müssen Sie zunächst einmal das Threat Model verstehen. Wie Sie bereits in Kapitel 4 erfahren haben, wird Threat Modeling von Sicherheitsexperten verwendet, um ausgehend vom gegenwärtigen Stand der Architektur, der Software und des Bedrohungsgrads geeignete Handlungen und Abhilfemaßnahmen zu bestimmen.

Wenn Sie ein Threat Model für den Einsatz von Encrypted Computation erstellen, müssen Sie bestimmen, wer an der Berechnung beteiligt ist und wie das mit dem Sicherheitsmodell (engl. Security Model) vereinbar ist.

Um eine solche Entscheidung leichter treffen zu können, werden Sie zunächst zwei Sicherheitsmodelle evaluieren (siehe Tabelle 7-1). Die Entscheidung ist, wie Sie bereits erfahren haben, mit gewissen Abwägungen verbunden. Obwohl Ihnen ein Malicious Security Model das höchste Maß an Sicherheit bietet, bringt es gleichzeitig ein langsameres und ressourcenintensiveres Protokoll mit sich. Bei einigen Protokollen gibt es zudem nicht die Möglichkeit, ein Malicious Security Model zu implementieren.

Tabelle 7-1: Sicherheitsmodelle in der Encrypted Computation

Sicherheitsmodell

Beschreibung

Semi-honest (alias »Honest but Curious« oder Passive Security)

Sie gehen davon aus, dass sich die Parteien an das Protokoll halten, aber dennoch versuchen werden, mehr Informationen über die geheimen Inputdaten der anderen in Erfahrung zu bringen, wenn sie dies ohne Weiteres tun können.

Malicious (oder Active Security)

Sie gehen davon aus, dass mindestens eine Partei bewusst versuchen wird, die Berechnungen zu manipulieren, indem sie nicht dem Protokoll folgt, Zwischenwerte verändert, die Berechnung abbricht oder sich mit anderen zusammenschließt, um Informationen zu den eingegebenen Daten zu erlangen.

Bei der Wahl eines Kryptosystems, d.h. eines Systems, das ein bestimmtes kryptografisches Protokoll und mehrere damit verbundene Methoden definiert, müssen Sie auch berücksichtigen, mit wem Sie zusammenarbeiten, und entsprechende Anforderungen an die Sicherheit festlegen. Wenn Sie zum Beispiel mit anderen Unternehmen zusammenarbeiten, die von einer dauerhaften Zusammenarbeit profitieren, ist es weitaus weniger wahrscheinlich, dass es zu bösartigen Aktivitäten kommt. In solchen Fällen könnte eine Verletzung des Protokolls als Verstoß gegen den zugrunde liegenden Vertrag bzw. die zugrunde liegende Vereinbarung angesehen werden. Insbesondere für Unternehmen, die gegenwärtig Daten im Klartext miteinander austauschen, wäre die zusätzliche Verschlüsselung im Rahmen eines Semi-honest-Modells für den Schutz der Privatsphäre der Individuen und die Geheimhaltung der Unternehmensdaten ein Fortschritt. Sie sollten Sicherheitsmodelle regelmäßig evaluieren und darauf achtgeben, inwieweit sie den aktuellen Anwendungsfällen und Sicherheitsanforderungen entsprechen.

Wenn Sie ein Threat Modeling für kryptografische Protokolle durchführen, interessieren Sie sich vor allem dafür, wie es um das Vertrauen und die Beziehung zwischen den Parteien steht. Dazu müssen Sie, wie in Tabelle 7-1 gezeigt, festlegen, welche Annahmen Sie über die anderen beteiligten Parteien zu treffen bereit sind. Außerdem müssen Sie externe Faktoren berücksichtigen, um einschätzen zu können, wie wahrscheinlich es ist, dass sich jemand böswillig verhält. Je nachdem, ob Sie in einer kleinen, vertrauten oder in großen, anonymen Gruppen zusammenarbeiten, sind die Implikationen ziemlich unterschiedlich.

In der kryptografischen Theorie gibt es verschiedene Ebenen von Sicherheitsgarantien – die informationstheoretische, die statistische und die effiziente bzw. komplexitätstheoretische Sicherheit (Computational Security) –, die bei der Modellierung des Problems und der potenziellen Bedrohungen zu berücksichtigen sind.

Wird ein Sicherheitsprotokoll zum ersten Mal konzipiert, wird ihm eine von drei theoretischen Geheimhaltungsgarantien zugewiesen (siehe Tabelle 7-2).

Tabelle 7-2: Sicherheitsgarantien von Verschlüsselungsprotokollen

Sicherheitsgarantie

Beschreibung

Informationstheoretisch

Selbst ein Angreifer, der über unbegrenzte Rechenleistung verfügt, kann das Verschlüsselungsverfahren nicht knacken.

Statistisch

Wenn der Angreifer über unbegrenzte Rechenleistung verfügt, gibt es eine kleine, statistisch bezifferbare Chance, dass er Werte wiederherstellen oder etwas in Erfahrung bringen kann.

Effizient (Computational Security)

Ein Angreifer, der über eine unbegrenzte Rechenleistung verfügt, hat zwar die Chance, etwas in Erfahrung zu bringen oder sogar einen Wert wiederherzustellen, allerdings ist er an die ihm verfügbare Rechenleistung gebunden.

Den höchstmöglichen Grad an Sicherheit garantiert die informationstheoretische Sicherheit. Es handelt sich dabei um die sogenannte unbedingte bzw. perfekte Sicherheit, die gegenüber einem böswilligen Angreifer absolut sicher ist, auch wenn dieser über unbegrenzte Rechenleistung verfügt.2 Ein Beispiel hierfür ist ein One-Time-Pad, eine Möglichkeit, einen String mit einem anderen gleich langen, zufällig generierten Schlüssel mittels einer XOR-Verknüpfung vollkommen zu sichern. Eine XOR-Operation erfolgt auf der Ebene von Bits und liefert den Wert 1, wenn beide Werte unterschiedlich sind, und den Wert 0, wenn sie identisch sind.

Statistische Sicherheit stellt die nächstniedrigere Stufe dar. Diese Sicherheit bieten oftmals informationstheoretische Protokolle, wenn sie in der Praxis umgesetzt werden. Beispielsweise kann es sein, dass ein Protokoll einen Pseudozufallszahlengenerator verwenden muss, der keine perfekte Zufälligkeit bietet. In den Implementierungen von Protokollen gibt es häufig statistische Sicherheitsparameter, mit denen die Sicherheit einer bestimmten Methode durch zusätzliche Informationen für den jeweiligen Anwendungsfall bzw. das konkrete Threat Model verbessert werden kann.

Die effiziente Sicherheit (Computational Security) stellt die letzte Stufe dar – sie garantiert, dass das Protokoll lediglich von einem motivierten Angreifer geknackt werden kann, der genügend Zeit und eine ausreichend hohe Rechenleistung zur Verfügung hat. Dementsprechend ist die Lösung der Aufgabe äußerst kostspielig, da es möglicherweise Jahre an Rechenzeit und eine große Anzahl an Recheninstanzen erfordert, um einen einzelnen Schlüssel oder eine einzelne Nachricht zu entschlüsseln. Viele Abschwächungen der informationstheoretischen Sicherheit fallen unter die effiziente Sicherheit. So bieten z.B. die zur Sicherung des gesamten Internetverkehrs und zur E-Mail-Kommunikation usw. verwendeten Verschlüsselungssysteme, bei denen öffentliche Schlüssel zum Einsatz kommen, alle eine effiziente Sicherheit.3

image

Wenn Sie sich die Implementierungen dieser Protokolle ansehen, hängen sie oft von den zugrunde liegenden Netzwerksicherheitsimplementierungen ab. Das bedeutet, dass die informationstheoretische Sicherheit oftmals auf die effiziente Sicherheit herabgesetzt wird, weil sie von Netzwerksicherheitsprotokollen wie TLS abhängen, die eine Generierung und einen Austausch von Schlüsseln unter Verwendung eines Verschlüsselungsprotokolls vornehmen, das auf öffentlichen Schlüsseln basiertt.

Verschiedene Arten der Encrypted Computation

In diesem Kapitel lernen Sie zwei verschiedene Arten von Encrypted Computation kennen: die Secure Multiparty Computation (im Deutschen auch als sichere Mehrparteienberechnung und im Englischen ebenfalls als Secure Computation bekannt) und die homomorphe Verschlüsselung (engl. Homomorphic Encryption, HE). Damit Sie die für Ihren Anwendungsfall richtige Wahl treffen können, sollten Sie mit diesen beiden Arten vertraut sein.

Secure Multiparty Computation

Secure Multiparty Computation (oft als SMPC oder MPC abgekürzt) ist ein Teilgebiet der Encrypted Computation, bei dem sich mehrere Parteien darauf einigen, die Berechnung zusammen durchzuführen, allerdings nur, wenn die Daten verschlüsselt sind. Viele MPC-Protokolle sind informationstheoretisch sicher und bieten verschiedene Garantien hinsichtlich des zu erwartenden Verhaltens dieser Parteien. Bei der Secure Multiparty Computation ist es wichtig, dass Ihr Sicherheitsmodell gut durchdacht ist.

Die Secure Multiparty Computation wurde erstmals in den späten 1970er-Jahren entwickelt, damit Onlinespiele für mehrere Spieler so gestaltet werden konnten, dass sie theoretisch fair sind. Die ersten Theorien wurden daraufhin als »Mental Poker« (https://oreil.ly/rqkng) bezeichnet.4 Ein relativ amüsantes Relikt aus dieser Zeit ist, dass die an einer Berechnung beteiligten Parteien oft als Player, also Spieler, bezeichnet werden. Seitdem hat sich MPC von den ursprünglichen theoretischen Überlegungen über die praktische Anwendung bis hin zur Konzeption von Protokollen weiterentwickelt und kommt seit Jahrzehnten in realen Anwendungsfällen und in der Secure Computation zum Einsatz.

Typischerweise gibt es bei der Secure Multiparty Computation mehrere Parteien (bzw. Spieler), die eine Funktion oder eine Reihe von Funktionen miteinander berechnen und auswerten wollen. Sie vertrauen einander jedoch nicht vollständig und/oder möchten ihre Inputdaten geheim halten. Dennoch vertrauen sie einander genug – bzw. sind durch das potenzielle Ergebnis der Zusammenarbeit ausreichend motiviert –, um die Berechnung gemeinsam durchzuführen und das Ergebnis einer oder mehreren Parteien offenzulegen. Hierbei ist eine Reihe von Anwendungsfällen denkbar, z.B. zwei oder mehr Unternehmen, die miteinander Daten austauschen, um ein gemeinsames Problem zu lösen, oder Situationen, in denen mehrere Akteure zusammenarbeiten, wie z.B. bei Abstimmungen, Auktionen und beim Austausch privater Daten, etwa bei der Bestimmung, welche Personen bei der Onlinepartnersuche zusammenpassen, oder bei einem DNA-Abgleich.

Zu den üblichen Schritten bei der Secure Multiparty Computation gehört die Verschlüsselung der Inputdaten durch geschickte mathematische Transformationen und schließlich die gemeinsame Nutzung der verschlüsselten Daten durch mehrere Parteien. Die Parteien arbeiten dann zusammen und tauschen Zwischenwerte aus, bis schließlich das Endergebnis über eine Reihe von Entschlüsselungsmechanismen und -interaktionen offengelegt wird.

Die Secure Multiparty Computation bietet einige interessante Geheimhaltungseigenschaften. Die an der Berechnung beteiligten Parteien möchten ihre Inputdaten geheim halten und sicherstellen, dass kein anderer Spieler viel über die von ihnen eingegebenen Informationen erfährt. Daher müssen die Protokolle so gestaltet sein, dass in den dazwischenliegenden Verarbeitungsschritten oder Funktionsauswertungen nichts über die Inputdaten preisgegeben wird. Erst wenn eine bestimmte Anzahl an Parteien für den letzten Schritt bereit ist, werden die Informationen im Rahmen der Entschlüsselung des Endergebnisses offengelegt.

MPC-Protokolle und -Schemata sind akkurat und robust. Einige Protokolle erfordern eine bestimmte Anzahl von Parteien, bevor das Endergebnis entschlüsselt werden kann, was oft als Schwellenwert (engl. Threshold) bezeichnet wird. MPC-Protokolle sind darauf ausgelegt, dass sie dasselbe Ergebnis liefern, das sie lieferten, wenn die Berechnung auf Basis der in Klartext vorliegenden Inputdaten erfolgen würde. Dies wird durch die hinter der Verschlüsselungsmethode stehende Mathematik gewährleistet, die Sie im folgenden Abschnitt anhand eines bestimmten Protokolls näher nachvollziehen werden. Einige wenige Protokolle setzen darauf, möglichst schnell oder äußerst leistungsfähig zu sein, und nehmen dafür eine geringe Fehlerquote in Kauf. Ein derartiger Kompromiss wird allerdings bei keinem der in diesem Kapitel vorgestellten Protokolle eingegangen.

image

Es gibt viele verschiedene MPC-Protokolle – Hunderte, wenn nicht Tausende –, und der Bereich wird fortlaufend weiter erforscht, Neues wird entdeckt und entwickelt. Wenn Sie sich eingehender mit den Protokollen beschäftigen möchten, empfehle ich Ihnen, einen Blick auf die in der MP-SPDZ-Bibliothek enthaltenen Protokolle (https://oreil.ly/ZFPXz) oder die SCALE-Bibliothek (https://oreil.ly/9Au0-) zu werfen, die unter der Führung von Spitzenforschern auf diesem Gebiet betrieben wird, unter anderem von Nigel Smarts Arbeitsgruppe (https://oreil.ly/g-ZaQ), die an der KU-Leuven in Belgien ansässig ist.5

Sehen wir uns nun eine beliebte Methode an, die als Secret Sharing bezeichnet wird, um besser zu verstehen, wie MPC funktioniert.

Secret Sharing

Beim Secret Sharing, also der gemeinsamen Nutzung von Geheimnissen, wird ein geheimer Wert in mehrere Teile (sogenannte Teilgeheimnisse bzw. Shares) dieses Werts aufgeteilt. Sie könnten beispielsweise eine Zahl haben, die Sie gern zu einer Berechnung beisteuern möchten, die aber verschlüsselt bleiben muss.

Sie könnten diese Zahl verschlüsseln, indem Sie eine zufällig generierte Zahl hinzuaddieren. Diese zufällig generierte Zahl stellt nun den Schlüssel dar und sollte geheim bleiben, damit sie von niemandem entschlüsselt werden kann. Wenn Sie das Ergebnis entschlüsseln wollen, ziehen Sie einfach die zufällig generierte Zahl ab. Dieser Ansatz eignet sich jedoch nicht im Rahmen datenwissenschaftlicher Zwecke, da dadurch die Möglichkeit zunichtegemacht wird, Berechnungen anzustellen.

Sie könnten auch den Ansatz verfolgen, das Rauschen und das Geheimnis in viele Teile aufzuteilen, wobei alle Teile wiederhergestellt werden müssen, damit das Ergebnis entschlüsselt werden kann. Dies wäre zum Beispiel dann sinnvoll, wenn zum Entschlüsseln eine bestimmte Anzahl von Spielern erforderlich ist oder wenn die Werte auf mehrere Personen (z.B. einen Ausschuss oder ein Gremium) oder auf mehrere Computer (z.B. in einer verteilten Architektur) verteilt werden sollen. Eine der Stärken von MPC ist, dass das Vertrauen zwischen diesen Parteien aufgeteilt wird – was auch die Art und Weise widerspiegelt, wie Menschen in der realen Welt Vertrauen verteilen.

Wenn Sie einen ganz simplen Ansatz verfolgen, könnten Sie einfach mehrere Zahlen zufällig auswählen und diese als One-Time-Pad (d.h. als einmalige Verschlüsselung) verwenden, indem Sie sie von dem Wert subtrahieren, den Sie verschlüsseln möchten. Im vorliegenden Beispiel ist der Wert, den Sie verschlüsseln möchten, x:

x = 45

keys = [100, 22, 43, 56]

enc_x = x - sum(keys) # enc_x entspricht dem Wert -176

# Zum "Entschlüsseln" addieren Sie die Schlüssel zum

# "verschlüsselten" Wert hinzu.

enc_x + sum(keys)

In diesem Fall können Sie dann die Schlüssel und enc_x an die verschiedenen Parteien verteilen. Jede der Parteien müsste diese Werte dann zusammenführen, damit sie x entschlüsseln können.

Aber dieser simple Ansatz hat einen unerwünschten Nebeneffekt: Es werden Informationen über x preisgegeben. Anhand des Vorzeichens des verschlüsselten Werts (hier enc_x) könnte ein neugieriger Mensch Informationen hinsichtlich der Größenordnung von x ermitteln (d.h., er könnte feststellen, ob es sich um eine große oder eine kleine Zahl handelt).

Es gibt bessere Methoden zur Erzeugung von »Schlüsseln« oder auch andere ausgeklügelte Möglichkeiten, diese Informationen geheim zu halten. Allerdings gibt es in der Kryptografie eine ausgezeichnete Methode, die als endlicher Körper (https://oreil.ly/ggFH9) (engl. Finite Field) bezeichnet wird. Wenn der Körper mithilfe einer Primzahl erstellt wird, lässt sich dieses Informationsleck ohne Weiteres beheben:

Q = 431

x = 45

keys = [100, 22, 43, 56]

enc_x = (x - sum(keys)) % Q image

image Hierbei handelt es sich um den Modulo-Operator (%), der den Rest bei einer Division zurückgibt. Bei Operationen mit Ringen bzw. Körpern stellt dies sicher, dass die Ergebnisse immer wieder auf den Anfangswert »umschlagen« und den Wertebereich des Körpers bzw. Rings niemals überschreiten.

Nun beträgt enc_x 255 anstelle von –176. Der Körper erlaubt es, dass die Zahlen nach Erreichen eines – durch die Modulo-Operation bestimmten – Maximalwerts wieder bei 0 beginnen, sodass die Größe von x im Körper selbst verborgen bleibt. Damit die Berechnungen mit dem Körper funktionieren, müssen die Schlüssel auch innerhalb des Körpers liegen, d.h., sie müssen kleiner sein als Q. Dies können Sie folgendermaßen sicherstellen:

num_players = 5

shares = [randrange(Q) for _ in range(num_players-1)]

shares += [(x - sum(shares)) % Q]

Als ich den Code ausführte, habe ich als shares die Werte [260, 163, 120, 82, 282] erhalten – bei Ihnen dürften sie jedoch anders ausfallen. Sie könnten diese Werte dann an die fünf beteiligten Parteien verteilen. Diese müssen die Werte erst miteinander kombinieren, um Ihren geheimen Wert aufdecken zu können. Das bedeutet, dass sie zusammenarbeiten und sich auf die Berechnung einigen müssen – womit das Vertrauen unter ihnen aufgeteilt wird.

Das Beste an diesem Ansatz ist jedoch, dass diese verschlüsselten Werte mit anderen verschlüsselten Werten von anderen Teilnehmenden addiert werden können, solange sie denselben Körper verwenden. Auf diese Weise lassen sich Summen, Durchschnittswerte und Zählungen für alle Teilnehmer verschlüsseln, die durch die Kombination aller Teilwerte entschlüsselt werden können. Das Ergebnis ist dasselbe, als wäre die Berechnung im Klartext durchgeführt worden. Dieser als Additive Secret Sharing bezeichnete Ansatz ist der einfachste für die gemeinsame Nutzung von Geheimnissen. Sie können den Ansatz in dem entsprechenden Notebook im Repository des Buchs einmal selbst ausprobieren.

image

Eine nützliche Eigenschaft von Operationen in einem endlichen Körper ist, dass es viele mögliche Erklärungen für die verschlüsselten Teilwerte gibt, die alle gleich wahrscheinlich sind, wenn ein Angreifer keine weiteren externen Informationen hat. Tatsächlich kann jedes Element des Körpers, also alle Zahlen zwischen 0 und der Größe des Körpers (Q), eine mögliche Erklärung sein! Secret Sharing bietet also informationstheoretische Sicherheit. Wenn Sie sich noch eingehender mit diesen Methoden beschäftigen möchten, sollten Sie sich Morten Dahls Beiträge zum Secret Sharing (https://oreil.ly/hKtu-) ansehen, die darüber hinaus auch begleitende Notebooks (https://oreil.ly/-md4f) enthalten.

Werfen wir nun einen Blick auf einen weiteren Ansatz, mit dem Sie die Teilwerte multiplizieren können und nach der Entschlüsselung das exakte Ergebnis erhalten.

Angenommen, Sie möchten zwei Zahlen, A und B, miteinander multiplizieren, wollen jedoch nicht, dass diese Werte im Klartext weitergegeben werden. Hierfür können Sie das Secret Sharing verwenden. Zunächst würden Sie die Werte so aufteilen, wie Sie es mit den additiven Werten getan haben, sodass jeder Wert in drei Teilwerten vorliegt. Dann können Sie diese Werte so verteilen, dass alle beteiligten Parteien zusammenarbeiten müssen, um die Berechnung der Multiplikation durchzuführen und die Lösung aufzudecken.

Sehen wir uns einmal an, wie das funktioniert:

  1. Spieler 1 und 2 teilen ihr Geheimnis jeweils in additive Teilwerte bzw. -geheimnisse (a1, a2, a3) und (b1, b2, b3) auf, wobei sie denselben endlichen Körper (Q) verwenden.
  2. Für die Berechnung wird ein dritter Spieler einbezogen, und die Teilgeheimnisse werden aufgeteilt. Spieler 1 besitzt A und behält a1 und a2. Zudem erhält er b2 und b3. Spieler 2 ist im Besitz von B und behält b1 und b2. Er erhält wiederum a1 und a3. Spieler 3 verfügt über keine eigenen Daten, beteiligt sich aber an der Berechnung, um die Geheimhaltung zu gewährleisten. Er erhält a2, a3, b1 und b3. Die Spieler sind nun bereit, die Berechnungen durchzuführen. Sofern sie nicht betrügen, indem sie Teilgeheimnisse entgegen der Protokolldefinition weitergeben, können sie auf der Grundlage der erhaltenen Teilgeheimnisse nicht auf das Geheimnis schließen.
  3. Jeder Spieler führt einen Teil der Berechnungen durch. Spieler 1 berechnet c1 = a1b2 + a1b3 + a2b2. Spieler 2 berechnet c2 = a1b1 + a3b1 + a3b2. Spieler 3 berechnet c3 = a2b1 + a3b3 + a2b3.
  4. Mittels Faktorisierung kann gezeigt werden, dass die Summe c1 + c2 + c3 dem Term a1(b1 + b2 + b3) + a2(b1 + b2 + b3) + a3(b1 + b2 + b3) entspricht, der wiederum (a1 + a2 + a3)(b1 + b2 + b3) bzw. A × B entspricht!

    Da die Spieler jedoch bereits in Schritt 2 einen Teil der Teilgeheimnisse gesehen haben, würde der Austausch der Zwischenwerte (c1, c2, c3) dazu führen, dass Informationen preisgegeben werden. Zur Vermeidung dieses Problems kann jeder Spieler seinen Zwischenwert verheimlichen, indem er ein zufälliges Element aus dem endlichen Körper hinzuaddiert (r1, r2, r3). Spieler 1 erhält von Spieler 2 c2 + r2 und berechnet c2 + r2r1. Spieler 2 erhält von Spieler 3 c3 + r3 und berechnet c3 + r3r2. Spieler 3 erhält von Spieler 1 c1 + r1 und berechnet c1 + r1r3. Da die Spieler die zufälligen Werte nicht austauschen, können sie keine zusätzlichen Informationen aufdecken, sofern sie nicht kollaborieren.

  5. Alle Spieler können nun ihre Ergebnisse bedenkenlos kombinieren, ohne dass dabei zusätzliche Informationen preisgeben werden, und A × B berechnen. Dazu können sie entweder alle Werte untereinander austauschen oder die endgültigen Werte an eine einzelne Partei übermitteln, die das Ergebnis dann bekannt geben kann. Dies wird im Voraus festgelegt und von allen Parteien vereinbart.

Wenn Sie nachvollziehen möchten, wie sich das Ganze programmieren lässt, finden Sie den entsprechenden Code im Repository des Buchs (https://github.com/kjam/practical-data-privacy).

image

Sie denken sich jetzt vielleicht: »Nun ja, wenn ich A kenne und weiß, was A mal B ist, dann kenne ich auch B.« Das ist richtig! Aber wenn Sie MPC verwenden, bilden Sie oft eine größere Berechnung ab, bei der die Multiplikation nur ein Teil davon ist. Die in diesem Kapitel vorgestellten Bausteine sollen Ihnen verdeutlichen, wie diese Protokolle funktionieren, sie sind jedoch nicht dazu gedacht, sie direkt zu implementieren und zu verwenden. Greifen Sie stattdessen auf eine gut getestete Kryptografiebibliothek zurück.

In Anbetracht der Sicherheitsgarantien, die die Parteien für ihre Geheimnisse erhalten, ist dies ein recht simples Protokoll. Es handelt sich jedoch um ein semi-honest bzw. passives Sicherheitsmodell. Sie vertrauen darauf, dass sich jede Partei an das vorgegebene Protokoll hält und keine Partei willkürliche Werte einbringt, mit denen sie versucht, mehr Informationen zu erlangen oder die Berechnungen zu stören. Darüber hinaus vertrauen Sie darauf, dass die Parteien nicht auf betrügerische Weise zusammenarbeiten und sich gegenseitig die erhaltenen Teilgeheimnisse zukommen lassen. Und zu guter Letzt vertrauen Sie darauf, dass die Parteien die Endergebnisse wie vorgesehen übermitteln, um das Ergebnis zu berechnen und die Berechnung nicht vorzeitig abbrechen.

Bei diesem Protokoll sind zwar drei Spieler beteiligt, aber nur zwei Spieler steuern Inputdaten bei. Zahlreiche Protokolle haben eine unterschiedliche Anzahl von Spielern und beteiligten Parteien. Einige erfordern auch einen Krypto-Dealer (engl. Crypto Provider), eine Funktion, die entweder eine vertrauenswürdige Partei übernehmen oder die mittels anderer Verschlüsselungsmethoden umgesetzt werden kann. Der Krypto-Dealer generiert Material, um die Geheimhaltungsgarantie aufrechtzuerhalten und Zwischenberechnungen zu beschleunigen. Dieses Material wird bereits vor Beginn der Berechnung in einer sogenannten »Offline«-Phase erzeugt, wodurch die Laufzeit verkürzt wird, da die Anzahl an Interaktionen zwischen den Parteien verringert wird.

Doch damit ist der Zauber noch nicht vorbei! Diese Operationen können auch umgekehrt werden, sodass eine Subtraktion oder Division ebenfalls möglich ist. In einem endlichen Körper sind diese Eigenschaften durch die Inverse des Körpers gegeben. Sie können das inverse Element der Subtraktion für jedes Element des Körpers wie folgt berechnen:

(x + y)modQ = 0

wobei y die Inverse ist und Q den Körper darstellt. Für einen Körper mit Q = 5 würden sich letztlich die in Tabelle 7-3 dargestellten Ergebnisse ergeben.

Tabelle 7-3: Additiv Inverse für Q=5

Ringelement

additiv Inverse

Beweis

1

4

(1 + 4) % 5 = 0

2

3

(2 + 3) % 5 = 0

3

2

(3 + 2) % 5 = 0

4

1

(4 + 1) % 5 = 0

Genau so, wie diese Elemente additiv Inverse haben, können Sie auch die multiplikativ Inverse ermitteln, um Divisionen im Körper durchzuführen.6 Diese wird wie folgt ermittelt:

(x * y)modQ = 1

An dieser Stelle verzichte ich darauf, die gesamte Tabelle für die multiplikativ Inverse durchzugehen. Es könnte Ihnen allerdings Vergnügen bereiten, wenn Sie sich ein paar Minuten Zeit nehmen und sie selbst berechnen. Sie werden merken, wie mächtig es ist, Operationen in einem Körper durchzuführen!

Um die additiv bzw. multiplikativ Inverse zu verwenden, können Sie die Ringinverse der Teilgeheimnisse anstelle der Teilgeheimnisse selbst anwenden. Im Repository des Buchs (https://github.com/kjam/practical-data-privacy) finden Sie mehrere Beispiele hierzu.

image

Die Beispiele in diesem Kapitel beziehen sich auf einen endlichen Körper bzw. einen Galoiskörper, da dieser besondere Eigenschaften besitzt. Diese Körper sind durch eine Primzahl definiert, in der Regel eine große Primzahl, damit die Zwischen- und geheimen Werte Werte innerhalb eines größeren Wertebereichs annehmen können. Wenn Sie für Q eine Zahl wählen, die keine Primzahl ist, ist es zwar möglich, einige Operationen auf der Grundlage der Eigenschaften eines Rings (https://oreil.ly/IGsyT) durchzuführen, aber diese gelten nicht für alle Operationen, die in einem Körper möglich sind. Dies wird beispielsweise deutlich, wenn Sie versuchen, die multiplikativ Inverse in einem Ring zu berechnen (d.h. Q=4 oder Q=6).

Es gibt mehrere weitere Secret-Sharing-Mechanismen, die effizienter und flexibler sind als die additive Methode, die Sie in diesem Abschnitt kennengelernt haben. Bei Shamir’s Secret Sharing können Sie z.B. einen Schwellenwert festlegen, sodass, wenn einige Spieler das Protokoll verlassen, die verbleibenden Spieler fortfahren und das Geheimnis rekonstruieren können. Die Wahl des Schwellenwerts bestimmt die Mindestanzahl der Parteien, die erforderlich ist, um das Geheimnis zu rekonstruieren und zu entschlüsseln. Sobald dieser Wert festgelegt wurde, bilden Sie ein Polynom vom Grad t – 1, wobei t die Anzahl der zur Entschlüsselung des Geheimnisses erforderlichen Spieler darstellt. Die Koeffizienten werden zufällig gewählt, und das Geheimnis wird im y-Achsenabschnitt festgehalten, d.h. bei x = 0.7 Um die Teilgeheimnisse zu verteilen, erhält jeder Spieler einen Punkt auf der Funktion – der ebenfalls nach dem Zufallsprinzip gewählt wird, allerdings ohne die Möglichkeit, dass x = 0 gewählt wird.

Damit das Geheimnis rekonstruiert werden kann, müssen mindestens t Personen ihre Teilgeheimnisse gegenseitig preisgeben. Anschließend wird das resultierende Polynom und das damit verbundene Geheimnis mittels Interpolation (https://oreil.ly/1srCK) offengelegt.

Sicherheitsmodelle in der Secure Multiparty Computation

Wenn Sie MPC verwenden, müssen Sie entscheiden, wie Sie das Vertrauen zwischen den Parteien verteilen, und festlegen, wie zu verfahren ist, wenn die Parteien nicht in gleichem Maße vertrauenswürdig sind. In den Beispielen, die ich Ihnen bisher gezeigt habe, haben Sie es mit einer semi-honest bzw. passiven Sicherheit zu tun gehabt. Dabei wird davon ausgegangen, dass die Parteien versuchen, so viel wie möglich aus den ihnen gegebenen Informationen in Erfahrung zu bringen, aber nicht aktiv vom Protokoll abweichen oder die Inputdaten böswillig verändern, um zusätzliche Informationen zu erlangen.

Es ist jedoch möglich, aktive Sicherheit für das Secret Sharing zu gewährleisten, indem Protokolle verwendet werden, bei denen geprüft werden kann, ob es sich um einen Betrug handelt, und die im Fall des Auffindens eines Betrügers den Prozess abbrechen. Eine Möglichkeit hierfür ist Verifiable Secret Sharing (VSS) (https://oreil.ly/LCddy), das eine aktive Sicherheit gegen böswillige Akteure bietet. VSS kann mittels verschiedener Protokolle implementiert werden. In der Regel übermittelt die Partei, die das Geheimnis verteilt, auch einen entsprechenden Wert, mit dem überprüft werden kann, ob die einzelnen Teilgeheimnisse korrekt formuliert sind.

Je nachdem, welches Protokoll verwendet wird, gibt es noch weitere Möglichkeiten, betrügerische Teilgeheimnisse aufzuspüren und diese auch zu korrigieren, sodass die Berechnung ohne die betrügerische Partei fortgesetzt werden kann. Bei Shamir’s Secret Sharing gibt es z.B. Fehlerprüfungs- und Korrekturcodes. Diese Varianten bieten häufig auch einen Schwellenwert, wodurch es den anderen Parteien ermöglicht wird, die Berechnung ohne den betrügerischen Spieler fortzusetzen. Wenn Sie einmal nachvollziehen möchten, wie sich dieses Protokoll implementieren lässt, empfehle ich Ihnen einen Blogbeitrag von Morten Dahl, in dem er sich mit diesen Korrekturmechanismen (https://oreil.ly/Pt815) befasst.

Bei der Verwendung von Secure Multiparty Computation zu berücksichtigende Faktoren

Wenn Sie sich dazu entschließen, Secure Multiparty Computation zu verwenden, müssen Sie verschiedene Faktoren wie Leistung, Architektur und Vertrauen berücksichtigen. Diese Faktoren spielen eine wichtige Rolle im Hinblick auf die Wahl des Protokolls und des Protokollschemas und können abhängig von der Implementierung sein. Das Spektrum an Implementierungsmöglichkeiten wächst von Jahr zu Jahr, da Secure Multiparty Computation zunehmend nicht nur in der Forschung, sondern auch in der Produktion Anwendung findet.

Welches Protokoll Sie wählen sollten und wie leistungsfähig es sein müsste, hängt maßgeblich davon ab, welche Art von Berechnungen Sie durchführen möchten. Dafür müssen Sie ermitteln, ob diese Berechnungen mit der von Ihnen ins Auge gefassten MPC-Bibliothek einfach oder schwierig sind. Je nach verwendetem Protokoll lassen sich bestimmte Operationen einfacher durchführen als andere. Zum Beispiel sind Vergleiche wie »größer als« oder »kleiner als« beim Secret Sharing relativ komplex und rechenintensiv, mit Methoden wie Garbled Circuits (https://oreil.ly/j3D3T) jedoch relativ einfach umzusetzen. Da man keinen einfachen Heuristiken folgen kann, welche MPC-Protokolle für welche Berechnungen am besten geeignet sind, sollten Sie derartige Entscheidungen den von Ihnen genutzten Bibliotheken bzw. Frameworks überlassen. Diese sind in der Lage, zu bestimmen, wie Operationen optimiert werden können, und können sogar die Wahl des kryptografischen Low-Level-Protokolls auf der Grundlage von Higher-Level-Spezifikationen der Berechnung (d.h. des in einer Higher-Level-Sprache verfassten Algorithmus) anpassen. Im Idealfall fungieren sie wie ein Compiler, der Ihren menschenlesbaren Code in Maschinenbefehle umwandelt, wobei die Optimierungen bereits in den Kompilierungsschritten vorgenommen werden.

Abwägungen im Rahmen der Bewertung des Einsatzes von Encrypted Computation

Zahlreiche Faktoren können sich auf die Geschwindigkeit Ihrer Berechnungen auswirken, unter anderem wie gut das Netzwerk optimiert ist und wie es eingerichtet wurde, wie hoch die Rechenleistung ist, wie der Algorithmus konzipiert ist, welches Verschlüsselungsschema und welche Bibliothek verwendet wird.

Häufig muss zwischen Benutzerfreundlichkeit und Leistungsfähigkeit abgewogen werden. Deshalb wird manchmal ein langsameres, aber einfacher zu verwendendes Protokoll gewählt, da es schlichtweg besser nachvollziehbar und wartbar ist.

Bei diesen Entscheidungen sollten Sie sich überlegen, von wem die Software und im Rahmen welcher Anwendungsfälle sie genutzt wird – und welche Einschränkungen Sie insbesondere hinsichtlich der Laufzeit und der Benutzerfreundlichkeit in Kauf nehmen wollen. Es lohnt sich, sich die Zeit zu nehmen, zunächst einige Frameworks bzw. Bibliotheken zu vergleichen und kleine Beispiele zu erstellen, um diese dann zu bewerten. Nur wenn die ersten Implementierungen gut gelingen und für Ihre Anwender nützlich sind, können Sie nachhaltige Anwendungsfälle schaffen, bei denen die eingesetzten Datenschutztechnologien ihre Wirkung entfalten und eine breitere Akzeptanz finden können.

Einen weiteren Faktor, den Sie berücksichtigen sollten, stellen die Eigenschaften des Körpers, mit dem Sie arbeiten, dar. In einem Körper operieren Sie mit Ganzzahlen. Im Rahmen von Data-Science-Anwendungsfällen, in denen Datenformate mit gemischter Genauigkeit (sogenannter Mixed-Precision) verwendet werden, muss nicht nur alles in Zahlen bzw. Tensoren umgewandelt werden, sondern es muss auch von der Gleitkommaarithmetik zur Festkommaarithmetik übergegangen werden. Dementsprechend müssen Sie bei der Entwicklung Ihres Algorithmus bzw. Ihrer Funktion darüber nachdenken, welche numerische Genauigkeit erforderlich ist. Gute Bibliotheken (wie die, die Sie in diesem Kapitel verwenden werden) sollten diesen Wechsel relativ problemlos bewältigen können. Wenn Sie jedoch mit sehr großen Ganzzahlen oder sehr kleinen Gleitkommazahlen arbeiten, sollten Sie einen Skalierungsfaktor berücksichtigen, bevor Ihre Daten im Rahmen einer Encrypted Computation verarbeitet werden.

Darüber hinaus sollten Sie sich auch über die Geschwindigkeit und Effizienz Ihrer Berechnungen Gedanken machen. Wie schnell Ihre Berechnungen vonstattengehen können, hängt von den verwendeten Protokollen ab und davon, ob es Möglichkeiten zur Optimierung gibt. Wie bereits im Abschnitt »Secret Sharing« auf Seite 238 erwähnt, gibt es eine Rolle, die als Krypto-Dealer bezeichnet wird und die dabei helfen kann, Optimierungen vorzunehmen und Offlineschritte für Berechnungen durchzuführen. Zudem gibt es auch Möglichkeiten für die Parteien, einige dieser Schritte in einer aktiveren Sicherheitsumgebung selbst vorzunehmen. Wenn Sie mehr über Protokolle erfahren möchten, die dies unterstützen, empfehle ich Ihnen, sich Morten Dahls Blogbeitrag zum SPDZ-Protokoll (https://oreil.ly/-3C6V) und den Forschungsbeitrag »Overdrive: Making SPDZ Great Again«, der Möglichkeiten zur Verbesserung des SPDZ-Protokolls (https://oreil.ly/RIVhS) aufzeigt, anzusehen.

MPC-Protokolle können in Bezug auf Parallelisierung und Timing optimiert werden. Wenn Sie mit mehreren Parteien zusammenarbeiten und sich gegenseitig Werte übermitteln, ist es wünschenswert, dass alle Spieler möglichst wenig Zeit damit verbringen, auf Zwischenergebnisse oder von den anderen Parteien gesendete Werte zu warten. Werden diese Berechnungsgraphen so optimiert, dass eine möglichst hohe Parallelisierung herbeigeführt wird, kann dies zu erheblichen Performance-Verbesserungen führen. Allerdings sollten Sie auch diese Optimierungen möglichst der verwendeten Bibliothek bzw. dem Framework überlassen.8

Darüber hinaus müssen Sie prüfen, wie stabil die Berechnungen vonstattengehen, d.h., ob es zu Ausfällen (Dropouts) von beteiligten Parteien kommen kann und, wenn ja, wie viele Teilnehmer ausfallen können, ohne dass die Berechnung zwangsläufig abgebrochen werden muss. Insbesondere dann, wenn viele Parteien beteiligt sind, kann es anfangs einige Versuche erfordern, einen geeigneten Schwellenwert zu finden. Daher sollten Sie zunächst auf Basis einer kleineren Anzahl von Parteien versuchen, einen geeigneten Schwellenwert zu finden, ähnlich wie Sie es bereits in Kapitel 6 kennengelernt haben. Wenn Sie nur eine kleinere Gruppe von Parteien einbeziehen, müssen Sie möglicherweise verlangen, dass mehr Teilgeheimnisse auf die Parteien verteilt werden, um eine etwaige Redundanz zu schaffen.

Servergestützte MPC

Eine weitere Möglichkeit, MPC-Protokolle zu optimieren, ist der Einsatz servergestützter MPC (engl. Server-aided MPC). Ähnlich wie Aggregatoren im Rahmen von Federated Analysis und Learning Unterstützung bieten, können auch Server als Zwischenstationen bzw. Knotenpunkte für MPC-Algorithmen und -Berechnungen fungieren.

In solchen Konstellationen können die Server gezielt platziert werden und für eine bessere Robustheit sorgen, da sie immer erreichbar sind. Damit die Sicherheitsanforderungen erfüllt werden können, müssen diese Server als Spieler direkt in die Berechnung einbezogen werden. Zudem muss der verwendete Algorithmus servergestützte MPC unterstützen.

Es gibt mehrere interessante Implementierungen servergestützter MPC, darunter eine von Microsoft Research, bei der Garbled Circuits zum Einsatz kommen (https://oreil.ly/f5EEx).

Darüber hinaus sollten Sie stets darauf achten, dass die von Ihnen verwendete Bibliothek umfassend geprüft und getestet wurde. Genauso wie bei Differential Privacy (siehe Kapitel 2) ist es wichtig, eine quelloffene und geprüfte Bibliothek zu finden, bei der Sie darauf vertrauen können, dass die Protokolle korrekt implementiert wurden. In der Kryptografie werden Open-Source-Lösungen im Grunde mehr Vertrauen entgegengebracht als proprietären Lösungen, da die Protokolle und Algorithmen von der gesamten Branche geprüft werden (Peer Review) und nicht nur von einer kleinen Gruppe interner Mitarbeiterinnen und Mitarbeiter bzw. Prüfer.

Angesichts der Tatsache, dass jede Partei im Rahmen mehrerer Schritte Daten an eine andere übertragen muss, wird deutlich, warum MPC als interaktionslastig bezeichnet wird. Je stärker sich die Daten im Cloud Computing und in Netzwerken konzentrieren und je mehr in die Optimierung von Netzwerkverbindungen investiert wird, desto geringer sind die mit den Interaktionen verbundenen Kosten. Das Secret Sharing ist zwar nicht das einzige MPC-Schema, das erwähnenswert ist, doch es ermöglicht zweifellos eine ganze Reihe von Operationen (Addition, Subtraktion, Multiplikation und Division) – und dies zu relativ geringen Kosten für alle beteiligten Parteien.

Im weiteren Verlauf des Kapitels werden Sie noch mit MPC experimentieren, wenn Sie das Moose-Framework für Encrypted Computation verwenden. Zunächst wollen wir jedoch andere Encrypted-Computation-Ansätze erkunden, die zwar weniger Interaktionen, dafür aber eine höhere Rechenleistung erfordern, wie etwa die homomorphe Verschlüsselung.

Homomorphe Verschlüsselung

Die homomorphe Verschlüsselung (engl. Homomorphic Encryption, HE) ist ein weiterer Teilbereich der Encrypted Computation, dessen Protokolle und Verfahren sich von der der MPC unterscheiden. Wie bei der MPC werden auch bei der HE die Ergebnisse berechnet, ohne dass die Daten dabei entschlüsselt werden. Bei der HE geschieht dies über spezielle Kryptosysteme, durch die die homomorphen Eigenschaften beibehalten und verschlüsselte arithmetische Operationen mit den Daten ermöglicht werden. Homomorphismus ist die Fähigkeit, algebraische Strukturen wie Gruppen oder Vektoren aufeinander abzubilden, wobei die mathematischen Eigenschaften bestimmter Operationen – wie Addition oder Multiplikation – erhalten bleiben. Bei der HE sind der Geheim- bzw. Chiffretext und der Klartext homomorph, sodass mathematische Operationen mit dem Chiffretext präzise durchgeführt werden können.

Im Vergleich zur MPC ist die HE sehr rechen- und speicherintensiv und erfordert daher eine wesentlich höhere Rechenleistung, um die Berechnungen durchführen zu können. Zudem erfordert sie nicht die Beteiligung von mehr als zwei Parteien, weshalb sie insbesondere dann geeignet ist, wenn es lediglich einen Dateneigentümer und einen Datenverarbeiter gibt, der Eigentümer der Daten jedoch möchte, dass die Daten während der Verarbeitung verschlüsselt bleiben. Dementsprechend bietet sich die Methode immer dann an, wenn ein Nutzer einen Teil seiner Daten verschlüsselt senden und eine verschlüsselte Antwort erhalten möchte, die er dann auf lokaler Ebene entschlüsseln kann.

Die Protokolle für die HE werden entweder als partiell bzw. teilweise homomorphe Verschlüsselung (engl. Partially Homomorphic Encryption, PHE) oder als voll homomorphe Verschlüsselung (engl. Fully Homomorphic Encryption, FHE) bezeichnet. Bei der PHE wird nur eine mathematische Operation unterstützt – als Operation kann entweder eine Addition oder eine Multiplikation durchgeführt werden, jedoch nicht beide gleichzeitig. Bei der FHE können jegliche mathematische Operationen mit beliebiger Schaltungstiefe (https://oreil.ly/1Gvs3) (engl. Circuit Depth) durchgeführt werden.9 Es gibt einige Protokolle, die eine abgestufte, voll homomorphe Verschlüsselung ermöglichen, bei der die Anzahl der Schaltkreise, die modelliert werden können, begrenzt ist.10

Bei der HE werden die homomorphen Eigenschaften der zugrunde gelegten Kryptosysteme genutzt. Die Kryptosysteme, die HE-Operationen unterstützen, stellen homomorphe Beziehungen zum Geheimtext her, wenn derselbe Schlüssel zum Verschlüsseln der Daten verwendet wird. Das bedeutet, dass Werte, die mit demselben Schlüssel verschlüsselt wurden, miteinander multipliziert werden können und eine verschlüsselte Darstellung des Produkts dieser Werte geliefert wird. Darüber hinaus können auch Operationen mit Klartextwerten durchgeführt werden und präzise verschlüsselte Ergebnisse geliefert werden. Die Werte können dann nur mit demselben Schlüsselpaar entschlüsselt werden, mit dem sie verschlüsselt wurden.

Im Gegensatz zu den meisten MPC-Protokollen ist es in der Regel erforderlich, die in den Zwischenschritten hinzugefügte Zufälligkeit zu reduzieren, da diese Kryptosysteme als Schutz vor statistischen Angriffen bereits einen Zufallsprozess beinhalten. Im Jahr 2009 kam es mit Gentrys Bootstrapping-Methode (https://oreil.ly/l1uyS) zum Durchbruch bei HE-Systemen, wodurch es im Rahmen der homomorphen Verschlüsselung erstmals möglich war, auch komplexere Operationen, Gatter und Algorithmen zu berechnen. Bis dahin gab es keine Möglichkeit, den zusätzlichen Zufallsprozess zu entfernen, der bei der Durchführung von homomorphen Operationen auf einem Teil eines Geheimtexts auftrat. Letztlich wurde dieses Rauschen so groß, dass das entschlüsselte Ergebnis verfälscht wurde.

Gentry konnte zeigen, dass der geheime Schlüssel selbst verschlüsselt und dann zur »Entschlüsselung« des Werts im verschlüsselten Raum verwendet werden kann. Sie können sich das wie eine doppelte Verschlüsselung vorstellen. Durch diesen Schritt konnte die zusätzliche Zufälligkeit im Geheimtext reduziert werden, ohne dass dadurch etwas über die Daten selbst preisgegeben wird. Da dieser Schritt zur Verringerung der Zufälligkeit als Zwischenschritt durchgeführt werden kann, ist es im Rahmen der HE möglich, mehr Operationen als zuvor durchzuführen. Sobald das Rauschen zu groß wird, wird der Bootstrapping-Schritt durchgeführt und dann mit den eigentlichen HE-Operationen fortgefahren. Diese Methode wird auch heute noch angewandt und ist in vielen FHE-Protokollen integriert.

Widmen wir uns nun einem einfachen homomorphen Verschlüsselungsprotokoll, damit Sie sich ein besseres Bild davon machen können, was es mit den homomorphen Eigenschaften auf sich hat.

Paillier-Verschlüsselung

Mithilfe des Paillier-Kryptosystems (https://oreil.ly/dE5xv) können additive homomorphe Verschlüsselungen durchgeführt werden, d.h., es können Zahlen addiert werden, während sie verschlüsselt bleiben. Ein Blick auf das Kryptosystem selbst verdeutlicht seine homomorphen Eigenschaften.

Um ein Schlüsselpaar aus einem öffentlichen und einem privaten Schlüssel zu erstellen, wählen Sie große Primzahlen mit einer bestimmten Eigenschaft und berechnen die abhängigen Werte mit einer zusätzlichen Zufallszahl. Am Ende erhalten Sie einen öffentlichen Schlüssel mit den beiden Werten (n, g) und einen privaten bzw. geheimen Schlüssel mit den beiden Werten (λ, μ).

Um eine Nachricht (m) zu verschlüsseln, berechnen Sie c = gm rn mod n2, wobei r im Rahmen gewisser Einschränkungen zufällig gewählt wird.

Beachten Sie den Homomorphismus, wenn Sie die Eigenschaften der verschlüsselten Nachricht nachvollziehen. Betrachten wir nun zwei Nachrichten m1 und m2.

Wenn Sie diese beiden Nachrichten mit demselben Schlüsselpaar verschlüsseln und sie miteinander multiplizieren, erhalten Sie:

(gm1r1n)(gm2r2n)modn2

Dies kann vereinfacht werden zu

(gm1 + m2(r1r2)n)modn2

was wiederum die Verschlüsselung von m1 + m2 darstellt. Wirklich genial, oder?

Damit Sie das neue Ergebnis entschlüsseln können, benötigen Sie den geheimen Schlüssel. Solange dieser geheim gehalten wird, sind also die Sicherheitseigenschaften gewährleistet.

Das Notebook mit dem entsprechenden Python-Code, der unter Verwendung von Klassen implementiert ist, finden Sie im Repository des Buchs (https://github.com/kjam/practical-data-privacy). Dort sind auch die zur Generierung der Schlüssel für die Ver- und Entschlüsselung erforderlichen Funktionen enthalten.

Zunächst müssen Sie die Schlüssel generieren und eine Nachricht verschlüsseln:

ek, dk = keygen() # ek ist der Chiffrierschlüssel, dk der Dechiffrierschlüssel

r = sample_randomness(ek) # zufälliger Wert, der als Teil der

# Verschlüsselung erforderlich ist

msg = 4

ciphertext = enc(ek, msg, r)

print(ciphertext)

Als Ausgabe sollten Sie jetzt eine sehr große Ganzzahl erhalten! Wenn Sie die Zelle erneut ausführen, wird das Ergebnis anders ausfallen, da sowohl die Schlüssel als auch der zufällige Wert unterschiedlich ausfallen werden.

Zur Entschlüsselung dieses Geheimtexts können Sie die im Notebook enthaltene Entschlüsselungsmethode verwenden:

dec(dk, ciphertext)

Durch deren Aufruf wird die korrekte Zahl (4) ausgegeben.

Wahrscheinlich kennen Sie bereits Systeme, die Nachrichten verschlüsseln und entschlüsseln können. Das Besondere an diesem System sind seine homomorphen Eigenschaften. Wie beim Secret Sharing können Sie Funktionen definieren, die die Eigenschaften eines Körpers ausnutzen. Mit den folgenden Funktionen – die ebenfalls im Notebook enthalten sind – können Sie Geheimtexte addieren und subtrahieren. ek.nn stellt einen Körper dar und besitzt somit diese nützlichen Eigenschaften:

def add_cipher(ek, c1, c2):

c = (c1 * c2) % ek.nn

return c

def neg(ek, c):

return inverse(c, ek.nn)

def sub_cipher(ek, c1, c2):

c = add_cipher(ek, c1, neg(ek, c2))

return c

Wenden Sie diese auf zwei verschlüsselte Werte an, können Sie sehen, dass sich mit ihnen verschlüsselter Text addieren und subtrahieren lässt. Wenn Sie das Ergebnis entschlüsseln, erhalten Sie das gleiche Ergebnis, als wenn Sie die Operation mit Klartext durchgeführt hätten. Genau so funktioniert die homomorphe Verschlüsselung:

msg_one, msg_two = 45, 234

c1 = enc(ek, msg_one, r)

c2 = enc(ek, msg_two, r)

result_addition = add_cipher(ek, c1, c2)

assert dec(dk, result_addition) == msg_one + msg_two

result_subtraction = sub_cipher(ek, c1, c2)

assert dec(dk, result_subtraction) == msg_one - msg_two

Sie können auch verschlüsselte Werte mit Klartextwerten addieren, subtrahieren und multiplizieren. Alle hier beschriebenen Methoden finden Sie im Notebook und können Sie selbst ausprobieren. Diese Implementierung unterstützt keine homomorphe Multiplikation, bei der die Zufälligkeit schneller wachsen würde und gegebenenfalls ein Bootstrapping erforderlich wäre, um die Zufälligkeit zu entfernen, ehe die Berechnung fortgesetzt werden kann.

image

Normalerweise würden Sie nicht »Ihre eigene Kryptografie entwickeln« oder kryptografische Protokolle von Grund auf neu schreiben. Dies ist nur ein Beispiel-Notebook, um Ihnen die Eigenschaften zu zeigen und Ihnen die Möglichkeit zu geben, ein wenig herumzuspielen und mehr darüber zu erfahren, wie diese Systeme funktionieren. Wenn Sie die Paillier-Verschlüsselung in der Praxis einsetzen möchten, sollten Sie sich die Bibliotheken ansehen, die diese Protokolle und Kryptosysteme unterstützen, wie z.B. python-paillier (https://oreil.ly/SCjOX) oder Paillier von Intel (https://oreil.ly/DllcL).

So beeindruckend die Paillier-Verschlüsselung auch sein mag, die meisten Kryptografen rücken von diesem System ab, da es nicht den heutigen Anforderungen an die Berechnungskomplexität (Hardness Assumptions) entspricht und im Vergleich zu anderen Methoden relativ langsam ist. Bei der Paillier-Verschlüsselung wird die Faktorisierung als Anforderung an die Berechnungskomplexität verwendet, die leistungsfähigsten und sichersten FHE-Verfahren basieren jedoch auf anderen schwierigen Problemen, wie dem des Lernens mit Fehlern (engl. Learning with Errors, LWE).

Lernen mit Fehlern (Learning with Errors)

Lernen mit Fehlern entwickelte sich ursprünglich auf der Grundlage von gitterbasierten Kryptosystemen (engl. Lattice-based Cryptosystems) und bahnbrechenden Arbeiten, die sich mit gitterbasierten Ansätzen und stochastischem Rauschen befassten.11 Bevor Sie weiter in die Materie eintauchen, sollten wir zunächst ein paar Begriffe klären.

Ein Gitter ist eine mathematische Struktur mit besonderen Eigenschaften – es definiert eine Basis für eine vollständige Menge linearer Vektorkombinationen, die viele mögliche Basen als Erklärungen haben können. In der Kryptografie bieten Gitter eine Alternative zu älteren Public-Key-Kryptosystemen wie RSA, Diffie-Hellman und Elliptische-Kurven-Kryptosystemen, die im Allgemeinen nicht quantensicher sind, da sie auf Faktorisierung beruhen. Gitterbasierte Kryptosysteme nutzen die Eigenschaften von Gittern, um spezielle Basisgitter zu erstellen, die sich bei der Strukturierung schwieriger Probleme als nützlich erweisen und von denen man annimmt, dass sie quantensicher sind.

Eines dieser schwierigen Probleme ist das des Lernens mit Fehlern. Dieses lässt sich in einigen wenigen Gleichungen vereinfachen.

In dem ursprünglichen Forschungsbeitrag von Oded Regev (https://oreil.ly/weWz4) geht es darum, wie sich ein Chiffrierschlüssel und ein Geheimnis erzeugen lassen, sodass andere Ihre verschlüsselten Nachrichten entschlüsseln können. Dazu wird zu Beginn eine Zufallskomponente aus einem Körper über q gezogen – etwa eine n-dimensionale Matrix (A). Diese Matrix fungiert wie ein Chiffrierschlüssel und wird zufällig aus einem Körper gezogen, wodurch sichergestellt ist, dass die Anforderungen hinsichtlich der Schwere (bzw. der Berechnungskomplexität) und der homomorphen Eigenschaften gewährleistet werden.

Anschließend erhält man einen Tensor s, der dem Geheimnis entspricht. Dann wird das Skalarprodukt der Matrix mit dem Tensor s gebildet, und es werden relativ kleine normalverteilte Fehler (〈an, sn〉 + en) hinzuaddiert. Die sich daraus ergebenden Modulo-Werte (d.h. der Rest der ganzzahligen Division) über dem Körper stellen eine gute Näherung für das Geheimnis dar – was allerdings nur sehr schwer festzustellen ist, wenn man A nicht genau kennt. Der letzte Schritt der Schlüsselgenerierung entspricht sTA + eT.

Zur eigentlichen Verschlüsselung der Daten wird die Nachricht vorbereitet, indem diese in einzelne Bitvektoren zerlegt wird, die mittels image berechnet und als image gespeichert werden. Anschließend können der generierte Schlüssel und das Geheimnis dazu verwendet werden, die Nachricht zu verschlüsseln, indem – wie beim Fehler – ein zufälliger Wert gewählt und image berechnet wird. Um die Nachricht zu entschlüsseln, muss man 〈c, smodq berechnen. Aufgrund des hinzugefügten Fehlers wird der Absolutwert des entschlüsselten Werts genommen und eine 1 ausgegeben, wenn dieser größer als q/4 ist, andernfalls eine 0.

Die homomorphen Eigenschaften werden – wie bei den zuvor beschriebenen Methoden – dank des Körpers beibehalten. In diesem Fall muss jedoch die zusätzliche Zufallskomponente berücksichtigt werden. Angenommen, Sie haben, wie zuvor beschrieben, zwei Geheimtexte und zwei Geheimnisse. Wenn Sie diese addieren und den Modulo über den Körper ermitteln, erhalten Sie im Grunde image + Zufallskomponenete. Dies führt zu mehr Rauschen, da der Fehler nicht nur einmal mittels Sampling hinzugefügt wird, sondern zweimal! Der Fehler darf nicht größer werden als q/4, ansonsten können die Werte nicht korrekt entschlüsselt werden.

image

Wenn Sie wissen möchten, wie dies im Fall der Multiplikation funktioniert, sollten Sie sich zunächst den erhellenden Einstiegsbeitrag von Stephen Hardy zum Thema Ring Learning with Errors (Ring-LWE) (https://oreil.ly/Zgjme) ansehen, um ein besseres Verständnis dafür zu entwickeln, wie Ringoperationen in einem polynomiellen Modulus funktionieren. Zudem können Sie sich die Vorlesungsunterlagen von Shai Halevi und Tal Malkin, die eine Einführung in das Schema und dessen Eigenschaften bieten, (https://oreil.ly/cBnZj) ansehen. Sollten Sie überdies Interesse daran haben, nachzuvollziehen, wie sich ein Ring-LWE programmieren lässt, empfehle ich Ihnen, sich die Codeimplementierung von Bill Buchanan (https://oreil.ly/a3Cx3) und Ayoub Benaissa, die auf dem OpenMined-Blog beschrieben werden, (https://oreil.ly/B-Rwx) zu Gemüte zu führen.

Nun, was hat das mit Gittern zu tun? Die Sicherheit dieses Schemas basiert auf der Komplexität bzw. Schwere von Gitterproblemen, da es sich auf bestimmte Probleme reduziert, die den Kern der Sicherheitsannahmen für Gitter bilden, wie das SIS-(Short-Integer-Solution-)Problem (https://oreil.ly/8CofL) und das Problem des kürzesten Gittervektors (engl. Shortest Vector Problem) (https://oreil.ly/M3nP1). Um mehr über die Komplexität dieser Probleme zu erfahren und darüber, wie es mit anderen Problemen der Kryptografie zusammenhängt, sollten Sie mit der Einführungsvorlesung in die gitterbasierte Kryptografie von Chris Peikert (https://oreil.ly/-ok5y) beginnen.

In diesem Beispiel fungiert Ihr A als Schlüssel, dessen Größe mit der Größe Ihrer Nachricht skalieren muss, was bedeutet, dass die Größe des Schlüssels sehr schnell zunimmt. Obwohl es diesbezüglich viele Verbesserungen gegeben hat, wird davon ausgegangen, dass größere Schlüssel erst in der Post-Quanten-Kryptografie zum Tragen kommen werden.

Die Grundform von LWE wurde zu mehreren Kryptoschemata erweitert, die HE-Operationen unterstützen. Ring-LWE und TFHE (https://www.tfhe.com) bieten beide vollständig homomorphe Operationen mit besseren Optimierungen. Die Torus-basierte HE verfügt beispielsweise über ein effizienteres Bootstrapping, das typischerweise den aufwendigsten Schritt in homomorphen Verschlüsselungs-Frameworks darstellt. Bei Ring-LWE werden die Berechnungen selbst um einige Polynome reduziert, wodurch die Bootstrapping-Schritte verkürzt werden.

image

Gitterbasierte und andere post-Quanten-kryptografische Verfahren kommen bereits in einigen aktuellen Implementierungen zum Einsatz, da sich die Unternehmen auf eine Zukunft vorbereiten, in der Quantencomputer größer sind und leichter zur Verfügung stehen. Google hat einige Zeit in seiner BoringSSL-Bibliothek NewHope verwendet (https://oreil.ly/jmK7D), und Microsoft hat in seiner Forschungsgruppe Ring-LWE-Schemata getestet (https://oreil.ly/KkXH-). Im Übrigen sind auch MPC-Verfahren quantensicher, sofern das zwischen den Spielern bestehende Netzwerk ausreichend gesichert ist.

Wenn Sie für Ihren Anwendungsfall FHE in Betracht ziehen, sollten Sie einen Blick auf die Concrete-Bibliothek von Zama (https://oreil.ly/Y8NuB) werfen, die eine ähnliche API wie NumPy hat. Interessant sind auch die SEAL-Bibliothek von Microsoft (https://oreil.ly/FTt3h) und die HElib-Bibliothek von IBM (https://oreil.ly/XBvcs), die mehrere Protokolle zur Verfügung stellen.

Faktoren, die bei der Verwendung homomorpher Verschlüsselung zu berücksichtigen sind

Wenn Sie HE in Produktionssystemen einsetzen möchten, sollten Sie über speziell entwickelte Hardware nachdenken, mit der Sie die Verarbeitungszeit erheblich verkürzen können. Es gibt Versuche, HE-Systeme zu beschleunigen, indem man Fieldprogrammable Gate Arrays (FPGAs) zur Optimierung von Berechnungen (https://oreil.ly/H_UFy) oder speziell entwickelte optische Systeme zur Beschleunigung des Suchvorgangs bei FHE (https://oreil.ly/gtUdG) verwendet.

Hierbei kann es sein, dass Sie Kompromisse zwischen Zweckdienlichkeit, Performance und Genauigkeit eingehen müssen. Einige der für die FHE optimierten Protokolle beruhen darauf, dass die als Teil des Prozesses hinzugefügte Zufälligkeit nicht immer beseitigt wird. CKKS (https://oreil.ly/EFqlf) ist ein Protokoll, das ein vertretbares Maß an Zufälligkeit erlaubt, sodass der Bootstrapping-Schritt umgangen wird. Wie bei Differential Privacy gibt es viele datenwissenschaftliche Probleme, bei denen die Einführung von Zufälligkeit von den Daten selbst erwartet wird. Sofern Sie sich mit einer näherungsweisen statt einer exakten Lösung arrangieren können, bieten diese Protokolle eine höhere Geschwindigkeit.

Einen weiteren Faktor, der Ihre HE-Implementierung beeinflusst, stellen Datengröße und Anzahl der erforderlichen Rechenoperationen dar. Manche Optimierungen funktionieren nur, wenn Ihre Daten relativ klein sind, wie etwa 8- und 16-Bit-Werte. Außerdem gibt es Berechnungen, die von einer kleineren Schaltung durchgeführt werden können, wodurch kostspielige Schritte wie Bootstrapping vermieden werden können. Während diese Optimierungen für erfahrene HE-Entwickler und Kryptografen auf der Hand liegen, dürften sie für Sie gegebenenfalls nicht so ersichtlich sein. Wahrscheinlich werden Frameworks diese Optimierungen künftig als Teil des Kompilierungsschritts unterstützen. Für den Moment sollten Sie sich einfach der möglichen Optimierungen bewusst sein, insbesondere dann, wenn Ihre Daten klein oder die Anzahl Ihrer Berechnungen relativ gering sind.

Zu guter Letzt sollten Sie Bibliotheken, Forschungsergebnisse und Entwicklungen in diesem Bereich im Auge behalten – in den vergangenen Jahren hat sich sehr viel getan. Es besteht immer die Möglichkeit, dass die sich weiterentwickelnde Rechenleistung oder die Entwicklung von Algorithmen und Hardware zu einem Durchbruch führt, durch den homomorphe Verschlüsselung zum festen Bestandteil der alltäglichen Berechnungen wird. Halten Sie sich über neue Forschungsentwicklungen und Implementierungen auf dem Laufenden, indem Sie den Beiträgen von Zama (https://www.zama.ai) oder Microsoft SEAL (https://oreil.ly/qfECd) folgen.12

image

Es würde den Rahmen dieses Kapitels sprengen, alle Bereiche der Encrypted Computation zu behandeln, weshalb ich nicht weiter auf Garbled Circuits und Oblivious Transfer (https://oreil.ly/4p-bA) eingegangen bin. Diese können in Bibliotheken und Frameworks, die Sie in diesem Kapitel kennengelernt haben, als Unterprotokolle verwendet werden, und bieten Optimierungen für bestimmte Operationen. Wenn Sie mehr darüber erfahren möchten, empfehle ich Ihnen, sich den Artikel A Pragmatic Introduction to Secure Multi-Party Computation (https://oreil.ly/zraeM) anzusehen.

HE-Berechnungen über Null-Wissen-Beweise validieren

Im Gegensatz zum Secret Sharing und den MPC-Verfahren gibt es bei HE-Operationen keine einfache Möglichkeit, einen möglichen Betrug zu erkennen und zu validieren. Sie können jedoch eine andere kryptografische Methode namens Zero-Knowledge Proofs, im Deutschen als Null-Wissen-Beweise bezeichnet, dazu nutzen.

Null-Wissen-Beweise basieren auf einer ungleichen Verteilung von Informationen, wobei der Beweiser (engl. Prover) Zugang zu geheimen Informationen hat. Daneben gibt es auch einen Verifizierer (engl. Verifier), der validieren möchte, dass der Beweiser diese Informationen tatsächlich besitzt. Der Beweiser möchte zeigen, dass er die Informationen kennt bzw. besitzt, ohne dabei die Informationen selbst preiszugeben, und der Verifizierer möchte den Beweis so oft anfordern, bis er sicher ist, dass der Beweiser die Ergebnisse nicht verfälscht hat. Diese Beweise können sowohl interaktiv sein – d.h., dass beide Parteien online sind und in Echtzeit antworten – als auch nicht interaktiv (d.h. offline bzw. als signierte Beweise, die an einem öffentlichen Ort bekannt gemacht werden). Diese Beweise können für eine Vielzahl weiterer Anwendungsfälle herangezogen werden, z.B. für die Onlinevalidierung persönlicher Informationen oder für den Nachweis, dass man im Besitz bestimmter Daten ist.

Im Rahmen eines HE-Anwendungsfalls könnte eine Partei zusätzliche Berechnungen mit den verschlüsselten Daten durchführen – vor allem wenn sie von diesen Änderungen profitieren könnte. Stellen Sie sich vor, Sie laden einen verschlüsselten Wert hoch und die andere Partei bietet Ihnen einen Dienst an, der auf dem zugrunde liegenden Wert der Daten basiert, z.B. eine Empfehlung oder eine Optimierung, wenn der Wert zu niedrig oder zu hoch ist. Was würde die andere Partei davon abhalten, die Berechnung zu ändern, um Ihnen einen Anreiz zu geben, den Dienst zu nutzen? Oder was hindert jemanden in einer Gruppenkonstellation – z.B. bei einer Auktion oder einer Wahl – daran, Ihre Inputdaten zu kopieren, mit ihnen Operationen durchzuführen und sie als seine eigenen zu übermitteln?13

In Szenarien wie diesen können Null-Wissen-Beweise als Audit Trail hinzugefügt werden. Darüber hinaus können sie auch als Beweis dafür dienen, dass man im Besitz des ursprünglichen verschlüsselten Werts und des Chiffrierschlüssels ist. Im Bereich des Machine Learning wurden beim zk-ml-Protokoll (https://oreil.ly/jwX8X) Null-Wissen-Beweise verwendet, um zu beweisen, dass das Modell ordnungsgemäß trainiert wurde und um die Ergebnisse zu validieren. Eine weitere ähnliche auf den MNIST-Daten basierende Implementierung (https://oreil.ly/PeXsy) befasste sich mit der Validierung sowohl des Modells als auch seiner Inputdaten.

Bei Berechnungen, die nicht im Rahmen von Machine Learning durchgeführt werden, können Sie sich vorstellen, einen nicht interaktiven signierten Beweis oder einen Endpunkt für einen interaktiven Beweis zu veröffentlichen, um zu bestätigen, dass Sie im Besitz der Inputdaten oder der zur Berechnung verwendeten Verarbeitungssysteme sind. Für diejenigen, die die Berechnung bereitstellen, könnten Sie auch einen Audit Trail für die Verarbeitung als Null-Wissen-Beweis bereitstellen. Diese würden ähnlich wie signierte Softwarebinärdateien funktionieren, sodass interessierte Parteien die eingegebenen und verarbeiteten Daten validieren können.

Nachdem Sie die Encrypted Computation nun grundlegend verstanden haben, wenden wir uns realen Anwendungsfällen zu und kommen so von der Theorie zur Praxis.

Reale Anwendungsfälle im Zusammenhang mit Encrypted Computation

Damit Sie einen Einblick in reale Problemstellungen und Lösungen im Bereich der Encrypted Computation erhalten, werden wir uns nun mit Private Set Intersection, Private Join and Compute, Secure Aggregation (bzw. sicherer Aggregierung) im Rahmen von Federated Learning (Kapitel 6) und Encrypted Machine Learning beschäftigen.

Private Set Intersection

Das Problem der Private Set Intersection (PSI, im Deutschen auch als private Schnittmengenberechnung bezeichnet) ist ein weitverbreitetes Rechenproblem, bei dem zwei oder mehr Parteien herausfinden möchten, ob und inwieweit sich ihre Daten überschneiden. Dabei kann es sich um nutzerbezogene Daten, potenzielle Kunden oder vertrauliche Geschäftsdaten handeln, wobei die Parteien die Berechnungen mit diesen Daten – aus welchen Gründen auch immer – nicht im Klartext vornehmen möchten.

Damit sie die Berechnung auf eine sichere Art und Weise erledigen können, entscheiden sich die Parteien, sie mittels PSI durchzuführen. Damit können sie die Datensätze im verschlüsselten Raum zusammenführen und entscheiden, wie die Schnittmenge entschlüsselt und offengelegt werden soll. Darüber hinaus gibt es Methoden, mit denen sich die Berechnung im verschlüsselten Raum fortsetzen lässt, anstatt die Schnittmenge zu entschlüsseln, worauf wir noch im Abschnitt »Private Join and Compute« auf Seite 259 eingehen werden.

Wie funktioniert nun die Private Set Intersection? Es gibt eine Vielzahl von Methoden und Protokollen. Im Folgenden lernen Sie eine einfache Variante kennen, die zwar nicht sehr effizient, aber leicht nachvollziehbar ist.

Die Diffie-Hellman-Methode im Rahmen der PSI

Schauen wir uns an, wie die Diffie-Hellman-Schlüsselaustauschmethode (https://oreil.ly/hPv0Y) funktioniert und wie sie im Rahmen der PSI verwendet werden kann.

Die Eingangssituation wird in Abbildung 7-1 dargestellt. Alice und Bob möchten einen gemeinsamen Schlüssel erstellen, mit dem sie Nachrichten verschlüsseln und miteinander kommunizieren können, ohne dass andere ihre Nachrichten lesen können.14

image

Abbildung 7-1: Der Diffie-Hellman-Schlüsselaustausch

Zur sicheren Erstellung eines gemeinsam genutzten Schlüssels müssen sie ein paar Informationen austauschen. Zunächst sendet Alice Bob einen Schlüsselgenerator und eine Primzahl. Diese müssen vorher gemeinsam festgelegt werden und werden manchmal von der verwendeten Software vorgegeben. Ihren privaten Schlüssel hält sie während des gesamten Austauschs geheim.

Bob verwendet die von Alice erhaltenen Informationen über den Generator und die Primzahl als Inputdaten, um sein eigenes öffentlich-privates Schlüsselpaar (Public-Private Key Pair) zu erzeugen und Alice seinen öffentlichen Schlüssel zu senden. Zu diesem Zeitpunkt können beide ihren privaten Schlüssel mit dem öffentlichen Schlüssel der anderen Partei verwenden, um einen gemeinsamen Schlüssel zu erzeugen.

In der Mitte der Abbildung befindet sich Eve, eine böswillige Angreiferin, die versucht, den Netzwerkverkehr abzuhören und den gemeinsam genutzten Schlüssel zu ermitteln. Doch selbst mit den Informationen, die Eve beim Abhören des Netzwerks sammelt, kann sie nicht auf den gemeinsamen Schlüssel schließen, wenn sie keinen Zugang zu einem der beiden privaten Schlüssel hat (oder zu einer Reihe anderer Informationen, wie etwa mehreren Klartextbeispielen oder der Ausgabe des Geheimtexts mit demselben gemeinsamen Schlüssel). Aus diesem Grund ist dieses Protokoll gegenüber einem Angreifer, der nur auf eine beschränkte Rechenleistung zurückgreifen kann, sicher.

Doch wie können Alice und Bob dieses Protokoll im Rahmen der PSI verwenden? Nun, sie könnten im Zuge der Generierung des gemeinsamen Schlüssels oder sogar im Rahmen des ursprünglichen Protokolls eine Darstellung ihrer Werte in Form eines Hashwerts mit ihren privaten Schlüsseln kombinieren, um Übereinstimmungen zu finden. Die einzelnen Schritte werden in einem Blogbeitrag von Will Clark beschrieben (https://oreil.ly/9DDUO) – im Wesentlichen handelt es sich um einen zusätzlichen Hashing-Schritt und ein paar weitere Interaktionen unter Verwendung der privaten Schlüssel zwischen Alice und Bob. Dies führt zu zusätzlichen Interaktionsschritten und erhöht die Größe der Nachricht im Vergleich zu dem einfachen Protokoll mit gemeinsamem Schlüssel, das in Abbildung 7-1 gezeigt wird.

image

Sie sollten sich stets über die neuesten Forschungsergebnisse auf dem Laufenden halten, denn jedes Jahr werden effizientere und schnellere Protokolle entwickelt. Viele Verbesserungsmöglichkeiten ergeben sich daraus, wie gut die beiden Datensätze eingeschätzt werden können – sind sie gleich groß, oder unterscheiden sie sich deutlich? Im weiteren Verlauf dieses Kapitels werden Sie noch eine Bibliothek kennenlernen, in der einige unterschiedliche Varianten implementiert sind, wobei die skizzierte Problemstellung Jahr für Jahr von Forschern optimiert wird.

Sie fragen sich jetzt vielleicht, wie sicher das ist. Könnte eine Partei nicht bezüglich ihrer Inputdaten lügen? Es gibt in der Tat Wege, auf denen eine der Parteien ihren ursprünglichen Datensatz abändern könnte, um herauszufinden, ob eine bestimmte Identifikationsnummer im anderen Datensatz enthalten ist. Eine der Parteien könnte sogar einen Datensatz erstellen, der alle denkbaren Varianten enthält, und so die Daten der anderen Partei vollständig offenlegen.

Das Protokoll ist daher nur in Umgebungen sicher, die eine semi-honest Sicherheit bieten. Es ist dennoch problemgerecht, da man für gewöhnlich nicht vorhat, seine Daten mit einem bekannten Angreifer zu teilen. Dementsprechend ist es auch wichtig, dass der genutzte Identifikator übereinstimmt. Sie sollten folglich sicherstellen, dass der Suchraum ausreichend groß ist oder dass alle Parteien dem Protokoll vertrauen. Wenn PSI in Produktionssystemen verwendet wird, geschieht dies in der Regel unternehmensintern, innerhalb eines multinationalen Unternehmens oder im Rahmen der Zusammenarbeit mit einem Geschäftspartner – dementsprechend ist die Wahrscheinlichkeit, dass jemand das Protokoll verletzt, um an weitere Informationen zu gelangen, relativ gering.

Es gibt noch einige andere Konfigurationen, die eine höhere Sicherheit bieten, wie z.B. Googles Implementierung von Private Join and Compute. Diese bietet auch noch weitere Vorteile, die wir nun einmal näher beleuchten werden.

Private Join and Compute

Googles quelloffene Implementierung von Private Join and Compute (https://oreil.ly/WcRf5), die auf einem Forschungsbeitrag aus dem Jahr 2019 (https://oreil.ly/l5_VB) basiert, verwendet ein PSI-Protokoll und berechnet auf der Grundlage dieser Werte eine Summe, anstatt die Schnittmenge an die Parteien zurückzugeben. Es wird im Rahmen eines speziellen Bereichs von Google Ads verwendet, um die Anzahl an Transaktionen zu berechnen, die einem Händler aus Google Ads zufließen.

In diesem Modell möchte Google dem Händler nicht alle Nutzerinnen und Nutzer, die eine Anzeige gesehen haben, anzeigen, da dies eine Verletzung der Privatsphäre der Nutzer darstellen und Unternehmensgeheimnisse von Google offenlegen würde (also was welchen Nutzern angezeigt wird). Dem Händler ist daran gelegen, nicht alle Transaktionen an Google zu übermitteln, da dies ebenfalls die Privatsphäre seiner Kunden verletzen und zu viele Informationen über sie und sein Geschäft preisgeben würde. Beide Seiten würden jedoch davon profitieren, wenn sie wüssten, wie viel Umsatz durch Werbung generiert wird, da sie so die Ausgaben für Werbeanzeigen, deren Inhalte und die Zuweisung von Budgets optimieren könnten.

Private Join and Compute funktioniert wie folgt: Zuerst wird eine Abwandlung eines Diffie-Hellman-Protokolls für PSI vorgenommen – mittels einer Hash-Funktion, die die Identifikatoren auf eine Gruppe in einem Körper abbildet. Dies geschieht in Verbindung mit privaten Schlüsseln, ähnlich wie beim Diffie-Hellman-Protokoll im Abschnitt »Die Diffie-Hellman-Methode im Rahmen der PSI« auf Seite 257. In diesem Fall sind die gemeinsam genutzten Datenpunkte die Nutzerkennung bzw. die Anzeigenkennung, die sowohl von Google als auch von dem Händler verwendet werden.

Als Nächstes verschlüsselt der Händler, der den Geldbetrag kennt, den ein bestimmter Nutzer in einem bestimmten Zeitraum ausgegeben hat, die je Nutzer getätigten Ausgaben mit einem additiv homomorphen Kryptosystem (hier: Paillier) und verknüpft diese mit den verschlüsselten Identifikatoren. Diese Werte werden an Google gesendet, wo sie auf der Grundlage der Schnittmenge entsprechend aggregiert werden (pro Nutzer, pro Anzeige, pro Zielgruppe usw.).

Das Endergebnis wird dann an den Händler gesendet, damit dieser es mithilfe seines privaten Schlüssels entschlüsseln kann. Zu diesem Zeitpunkt hat der Händler nur aggregierte Werte für die verschiedenen Kundengruppen erfahren, die einen Kauf getätigt haben, nachdem sie eine bestimmte Werbekampagne gesehen haben. Google hat keine weiteren Informationen über Nutzer erhalten, die nicht in der Schnittmenge enthalten sind.

Google hat sich für ein Protokoll entschieden, das auf dem ursprünglichen Diffie-Hellman-Schlüsselaustausch basiert, obwohl es weniger performant als andere ist. Dies war zum Teil der Einfachheit geschuldet – Softwareentwickler können das Protokoll gut nachvollziehen, wodurch sichergestellt wird, dass es auch sicher implementiert werden kann. Diesen Umstand sollten Sie im Hinterkopf behalten, wenn Sie Ihre eigenen Systeme entwerfen und gestalten. Wann immer es möglich ist, sollten Sie ein Design wählen, das auch für andere verständlich ist, solange es den Anforderungen der jeweiligen Aufgabe gerecht wird. Wenn eine Aufgabe zu komplex ist oder ein fortgeschrittenes Protokoll erfordert, müssen Sie sich darüber im Klaren sein, dass viele Menschen nicht in der Lage sein werden, das System zu aktualisieren, zu ändern oder zu debuggen.

Nachdem Sie nun ein einfaches Beispiel kennengelernt haben, bei dem HE dazu beiträgt, dass zwei Parteien Summen unter Wahrung der Privatsphäre (private Sum) berechnen, können wir uns jetzt ansehen, wie Encrypted Computation im Rahmen von Problemen im Bereich des Machine Learning eingesetzt werden kann.

Sichere Aggregierung (Secure Aggregation)

Federated Learning und Federated Analytics können, wie in Kapitel 6 erwähnt, von Encrypted Computation profitieren, indem sie für einen höheren Grad an Geheimhaltung sorgt. Eine Möglichkeit, die Sicherheit für die von den verschiedenen Teilnehmenden erhaltenen Aktualisierungen des Modells bzw. der Gradienten zu implementieren, ist die Einführung von MPC oder HE als Kernberechnung für die Aktualisierungen. Die Inputdaten von den einzelnen Edge-Geräten bzw. Endnutzern kommen beispielsweise verschlüsselt an und werden erst entschlüsselt, nachdem am Aggregationspunkt Differential Privacy hinzugefügt wurde. Dies bietet eine stärkere Garantie, dass der Aggregator nur sehr wenig über die jeweiligen Inputdaten erfährt und dass im Fall eines Angriffs auf den Aggregator dieser die einzelnen Aktualisierungen nicht aufschlüsseln kann.

Wie genau das funktionieren könnte, werden wir anhand des Beispielprozesses in Abbildung 7-2 nachvollziehen.

image

Abbildung 7-2: Sichere Aggregierung unter Verwendung von Secret Sharing

Angenommen, auf einer Vielzahl von Geräten wird lokal ein Modell trainiert, und die Gradienten werden jeweils aktualisiert, wobei diese anschließend übermittelt werden sollen (wie auf der linken Seite in Abbildung 7-2 gezeigt).

Sobald das Training beendet ist und die Geräte bereit sind, die aktualisierten Gradienten zu senden, können sie, anstatt sie im Klartext an einen Aggregator zu senden, jeweils geheime Anteile ihrer Gradienten (bzw. Teilgeheimnisse) an mehrere Aggregatoren senden. Die Aggregatoren sammeln diese verschlüsselten Teilgeheimnisse und ebenso die Anzahl der Spieler, die ihnen Teilgeheimnisse geschickt haben. Alle Gradienten müssen auf Ebene der Geräte gestutzt werden (Clipping), ehe sie verschlüsselt werden, doch das für Differential Privacy erforderliche Rauschen wird über die Aggregatoren als Teil einer »verrauschten« Summenbildung hinzugefügt. Die Aggregatoren können entweder verrauschte Summen oder verrauschte Durchschnittswerte zusammenführen, sodass letztlich ein föderaler Durchschnitt gebildet wird (siehe Kapitel 6).

Denken Sie daran, dass Sie besondere Vorkehrungen für Dropout-Schichten treffen müssen, da die Teilgeheimnisse vollständig sein müssen. Darüber hinaus erfordert diese Architektur ein zusätzliches Maß an Engineering und Zufälligkeit. Dieses zusätzliche Rauschen kann sich je nach Daten und Aufgabenstellung positiv oder auch negativ auf das Training eines Modells auswirken.

Diese Architektur gewährleistet den Schutz der Privatsphäre und die Geheimhaltung der Aktualisierungen, während sie gleichzeitig ermöglicht, dass die Aktualisierungen (bzw. aktualisierten Gradienten) akkurat sind. Darüber hinaus bietet sie Flexibilität hinsichtlich des Designs des Systems und der Architektur und sorgt dafür, dass die Aktualisierungen sicher sind, da sie nun auf mehrere Aggregatoren verteilt sind. Dadurch sind sie gegenüber einer einfacheren, böswilligen Aggregator Attack (bei der ein Aggregator kompromittiert wird und somit alle Gradienten für den Angreifer zugänglich werden) weniger anfällig.

image

Das ist nur ein Beispiel für eine sichere Aggregierung. Jason Mancuso und das Team von Dropout Labs haben die erste Open-Source-Implementierung für die sichere Aggregierung mit HE und dem Paillier-Kryptosystem in TensorFlow vorgestellt. Es gibt auch einen Blogbeitrag (https://oreil.ly/Judux), in dem die Vorgehensweise beschrieben wird. Den Code finden Sie im entsprechenden Repository (https://oreil.ly/o31Vl), sollten Sie ihn testen und nachvollziehen wollen. Dieser Ansatz nutzt einen weiteren Server und ein paar Schritte zur Schlüsselgenerierung und -verteilung, weshalb er relativ effizient ist, wenn viele Geräte daran beteiligt sind.

Wenn Sie Gradienten im verschlüsselten Raum aktualisieren können, können Sie dann auch ein ganzes Modell mit verschlüsselten Daten trainieren? Ja, auch das ist möglich! Werfen wir doch gleich einen Blick auf das spannende Feld des Encrypted Machine Learning.

Encrypted Machine Learning

Encrypted Machine Learning ist ein vielversprechender Bereich, in dem die fortschrittlichen Forschungsmethoden und Protokolle der Encrypted Computation in die Praxis umgesetzt werden, da sie ermöglicht, Machine Learning mit verschlüsselten Daten durchzuführen. Was wäre, wenn Sie Modelle ausschließlich auf verschlüsselten Daten trainieren und sensible Daten während des Modelltrainings sicher und geheim halten könnten? Dadurch würden sich völlig neue Anwendungsfälle eröffnen, in denen Daten derzeit nicht verwendet werden können, da sie nicht entschlüsselt weitergegeben werden dürfen. Neue Formen der Zusammenarbeit und der gemeinsamen Nutzung von Daten wären dadurch möglich. Krankenhäuser könnten zusammenarbeiten, um Algorithmen zur Krebserkennung zu trainieren. Regierungen könnten gemeinsam Modelle trainieren, um den Klimawandel zu bekämpfen. Konkurrenten in Bereichen wie Transport, Logistik, Internetworking und Sicherheit könnten sich zusammenschließen, um Systeme zu optimieren, bei denen es mehrere mehrere Dateneigentümer gibt.

Es gab bereits in den 1990er-Jahren eine Reihe von auf dem Gebiet der Encrypted Computation forschenden Wissenschaftlern, die verschiedene Ideen für Encrypted Machine Learning vorschlugen. Doch das erste Forschungspapier, das auch eine Open-Source-Implementierung beinhaltete, wurde erst im Jahr 2016 von Microsoft Research veröffentlicht und trug den Titel CryptoNets (https://oreil.ly/9pLU9). Die Autoren implementierten mithilfe von Microsofts SEAL-Bibliothek ein neuronales Netz (engl. Neural Network), bei dem homomorphe Verschlüsselung zum Einsatz kam. Das einfache Convolutional Neural Network, das in dem Forschungspapier vorgeschlagen wurde, konnte anschließend erfolgreich auf den MNIST-Daten trainiert werden. Die entsprechende Implementierung können Sie sich auf GitHub (https://oreil.ly/3KVv6) ansehen. Obwohl es sich lediglich um eine Optimierung früherer Arbeiten handelte, dauerte jede Vorhersage auf einem handelsüblichen Laptop etwa vier Minuten. Anschließend optimierten sie es noch weiter, indem sie dafür sorgten, dass die Vorhersagen auch für Batches vorgenommen werden konnten, dass also Vorhersagen für mehrere Inputdaten auf einmal gemacht werden konnten.

Mittlerweile gibt es mehrere reale MPC-Anwendungen, sodass Encrypted Learning nicht mehr nur in der Forschung, sondern auch in der Praxis zum Einsatz kommt. Ich hatte das Vergnügen, mit dem Team von Dropout Labs zusammenzuarbeiten, das die erste in der breiten Öffentlichkeit genutzte Bibliothek für Encrypted Learning – tf-encrypted (das steht für TensorFlow Encrypted) (https://oreil.ly/bfH1_) – entwickelt hat.

Wie funktioniert tf-encrypted? In der Bibliothek werden die im Abschnitt »Secret Sharing« auf Seite 238 beschriebenen grundlegenden MPC-Verfahren verwendet, aber auch noch zusätzliche Schichten (engl. Layer) zur Bildung von Summen, bei denen der Schutz der Privatsphäre gewahrt bleibt (mittels Maskierung – d.h. in diesem Zusammenhang, dass die Zwischenwerte, mit denen auf die individuellen Teilgeheimnisse rückgeschlossen werden könnte, nicht eingesehen werden können – und Hinzufügen von zufälligem Rauschen, das später wieder entfernt wird). Sie ermöglicht zudem eine Multiplikation und eine Division von Tensoren auf verschlüsselte Weise und bietet verschiedene Machine-Learning-Optimierungsverfahren wie die ReLu-Aktivierungsfunktion.15

Eine der Schwierigkeiten, auf die das Team von Dropout Labs stieß, war eine Möglichkeit, zu implementieren, dass die beteiligten Parteien überprüfen können, ob alle Parteien die Berechnungen wie erwartet durchführen, sowie auf die Berechnung zwischen den Parteien schließen zu können. Bevor ein Protokoll ausgeführt wird, müssen sich die Parteien darauf einigen, was berechnet werden soll, und darauf vertrauen, dass die Berechnung entsprechend ihren Erwartungen und Anforderungen vorgenommen wird. Um sicherzustellen, dass sich alle Parteien an das Protokoll halten, und um die Kompilierung und Implementierung des Protokolls zu optimieren, musste das Team eine sichere Laufzeitumgebung entwickeln, die von einem Data Scientist leicht zu verstehende Higher-Level-Anweisungen in MPC-Protokollen ausführen kann, die wiederum von einem Kryptografen validiert werden könnten.16

Es war sicherlich kein leichtes Unterfangen, aber die Ergebnisse sind nun quelloffen und können von jedem genutzt werden, der Berechnungen auf verteilte und sichere Weise durchführen möchte. Im nächsten Abschnitt lernen Sie, wie Sie die sichere Laufzeitumgebung Moose (https://oreil.ly/ih1lw) und die Higher-Level-Programmiersprache pyMoose (https://oreil.ly/dsJ6Z) nutzen können, um Ihre eigenen Berechnungen mit verschlüsselten Daten durchzuführen.

Encrypted Retrieval Augmented Generation

Encrypted Computation lässt sich nicht nur im Rahmen des Trainings oder von Vorhersagen (Inferenz) in sensiblen Kontexten heranziehen, sondern auch bei generativen Modellen und in Text- und Informationssuchsystemen (engl. Information Retrieval Systems). Angesichts der wachsenden Beliebtheit von Large Language Models (LLMs) werden zunehmend auch Retrieval-Augmented-Generation-(RAG-)Systeme eingesetzt. Bei einem RAG-System wird ein Large Language Model (LLM) mit einer privaten oder öffentlich zugänglichen Datenquelle, wie einem Dokumentenspeicher oder einem halbstrukturierten Datensatz, kombiniert. Dieser Ansatz bietet eine Alternative zu älteren Information-Retrieval-Systemen, die zur Beantwortung von Benutzeranfragen eingesetzt werden, wie z.B. Such- und Abfragesysteme, die auf der Ähnlichkeit von Dokumenten, dem Clustering oder anderen traditionellen NLP-Ansätzen basieren. RAG-Systeme können solche Suchvorgänge über eine Vielzahl von Datenquellen auf der Basis von Prompts bzw. Abfragen eines Nutzers durchführen und die Ergebnisse anschließend mithilfe eines LLM oder eines anderen generativen KI-Systems zusammenfassen, d.h. der eigentliche Vorgang des Retrieval wird noch ergänzt (»augmented«). Diese Suche kann mit Encrypted Computation kombiniert werden, um sowohl die Abfrage als auch die Dokumente besser zu schützen.

Ähnlich wie beim Private Information Retrieval (PIR) könnte ein RAG-System als ein Abfragesystem, bei dem die Privatsphäre gewahrt bleibt, aufgefasst werden, d.h., der Prompt selbst (bzw. die Tokens und deren Tensordarstellung) wird verschlüsselt. Je nach Abfragemethode und Sensibilität des Datenspeichers und der Informationen, die abgefragt werden sollen (also der Dokumentenspeicher bzw. der Text, der abgerufen werden soll), könnte die Suche auch auf verschlüsselte Weise (bzw. im verschlüsselten Raum) erfolgen.

Mehrere Forscher am MIT konnten nachweisen, dass dies mit Techniken des Secret Sharing möglich ist (https://arxiv.org/abs/2311.12955), sodass mehrere Dokumentenanbieter ihre Dokumente für die Suche zur Verfügung stellen können, während die Privatsphäre gewahrt und der Prompt geheim bleibt. Sie verwendeten den k-Means-Clustering-Algorithmus, um die Dokumente in Regionen einzuteilen. Die Dokumente selbst bleiben jedoch verschlüsselt und sind auf mehrere Dokumentenanbieter verteilt. Der Prompt wird verschlüsselt, und PIR wird verwendet, um die relevanten Cluster zu finden, ohne dass diese Cluster den Eigentümern der Dokumente offengelegt werden. An diesem Punkt kann der Retrieval-Prozess auf der Grundlage der verschlüsselten Abfrage den entsprechenden Text in den abgerufenen Dokumenten finden und den entschlüsselten Text an den Nutzer zurückgeben. Die Forscher haben auch ein schnelleres Protokoll vorgeschlagen, bei dem jedoch einige Informationen über den Prompt und die Abfrage preisgegeben werden, da den Dokumenteneigentümern die k ausgewählten Cluster offengelegt werden (allerdings nicht die Abfrage selbst).

Obwohl die Forschung im Bereich Encrypted Retrieval Augmented Generation noch in den Kinderschuhen steckt, könnten zukünftige Entwicklungen in diesem Bereich zu einem besseren Schutz der Privatsphäre der Nutzerinnen und Nutzer und ihrer Abfragen führen und es Unternehmen ermöglichen, vertrauliche interne Dokumente einem begrenzten Personenkreis (z.B. ihren Mitarbeitenden) zur Verfügung zu stellen, ohne diese Daten gleichzeitig an einen Drittanbieter von LLMs weitergeben zu müssen. Sie sollten daher diesen Forschungsbereich unbedingt im Auge behalten. Es könnte hier in den nächsten Jahren zu einem Durchbruch kommen.

Die ersten Schritte mit PSI und Moose

Moose ist eine sichere Laufzeitumgebung, die High-Level-Berechnungsgraphen (bzw. gerichtete azyklische Graphen [engl. Directed Acyclic Graphs, DAGs]) in MPC-Protokolle und einen physischen Ausführungsplan umwandelt. Ähnlich wie bei den inneren Abläufen von Spark, die in Abbildung 6-1 gezeigt werden, nimmt Moose den NumPy-ähnlichen High-Level-Code und kompiliert ihn in Code, der von einem Kryptografen validiert werden kann. Anschließend kann es diesen Code in einen logischen Plan und einen physischen Plan kompilieren, die auf den bestehenden Netzwerkknoten ausgeführt werden.

Moose wurde speziell dafür entwickelt, dass Data Scientists zusammenarbeiten und verschlüsselte Datenflussdiagramme erstellen können, ohne dass sie dabei von einem Kryptografen unterstützt werden müssen. Falls es dennoch ein Sicherheitsoder Kryptografieteam gibt – oder wenn die Data Scientists die Berechnung mithilfe eines externen Sicherheitsanbieters überprüfen möchten –, können Sie den Teams bzw. dem Sicherheitsanbieter die Bibliothek, den Compiler und das generierte MPC-Protokoll zeigen oder die jeweiligen Ansprechpartner den Graph selbst mit Moose kompilieren lassen.

Gehen wir einmal durch, wie zwei Parteien eine Kombination aus homomorphen Verschlüsselungstechniken und MPC verwenden können, um gemeinsam bestimmte Werte zu ermitteln und diese auf sichere Weise zu berechnen. Angenommen, Sie arbeiten in einem Unternehmen der Konsumgüterbranche, das seine Umsatzdaten mit einem anderen Unternehmen vergleichen möchte, um neue Möglichkeiten der Produkt- und Marketingzusammenarbeit zu identifizieren. Jedes Unternehmen teilt seine Umsätze in bereits bekannte gemeinsame Gruppen ein, beispielsweise Einrichtungsgegenstände oder Sportbekleidung. Um eine mögliche Kooperation zu identifizieren, vergleichen die Unternehmen ihre Nutzerbasis, um gemeinsame Kunden finden. Anschließend berechnen sie, wie diese gemeinsamen Kunden ihr Geld in den verschiedenen Kategorien ausgeben, um festzustellen, ob es interessante Muster gibt. Um den Datenschutz und die Geheimhaltung zu gewährleisten, legen sie die Gesamtausgaben pro Kategorie nicht offen, sondern nehmen eine Berechnung vor, mit der sie den prozentualen Anteil der Ausgaben hinsichtlich einer Kategorie für einen bestimmten Nutzer ermitteln. Selbstverständlich muss auch für solche Berechnungen die Zustimmung der Nutzer eingeholt werden.

Für den ersten Schritt verwenden sie die Private-ID-Bibliothek von Facebook Research (https://oreil.ly/rNzel), mit der zwei Parteien mittels eines Private Join Überschneidungen zwischen ihren Werten ermitteln können (unter Wahrung des Datenschutzes). Die Bibliothek ist in Rust programmiert und erfordert, dass zunächst mehrere Komponenten kompiliert werden, ehe alle Befehle ausgeführt werden können. Den im Folgenden dargestellten Code können Sie auch anhand des Notebooks im Repository des Buchs (https://github.com/kjam/practical-data-privacy) nachvollziehen und ihn selbst ausführen.

Nach der Installation der Private-ID-Bibliothek erstellt jede Partei eine CSV-Datei, die unter anderem die Identifikatoren, die sie im Rahmen der Berechnung vergleichen möchte, enthält. Die Parteien müssen sich auf ein gemeinsames Datenelement einigen, das eine eindeutige persönliche Identifizierung erlaubt. Im vorliegenden Beispiel ist dies die E-Mail-Adresse der Kunden, aber es könnte auch ein Identifikator sein, der aus verschiedenen Elementen wie z.B. dem Namen, der E-Mail, dem Geburtsdatum usw. besteht – vorausgesetzt, jede Partei verfügt über diese Informationen.

Jede Partei betreibt einen Private-ID-Server. Dabei ist es wichtig, einen Weg zu finden, wie diese Server miteinander kommunizieren können. Hierzu bietet die Bibliothek einige Möglichkeiten sowie mehrere Protokolle, die abhängig von der Größe des Datensatzes verwendet werden können. Wie in Kapitel 6 empfohlen, sollten Architektur- und Sicherheitsteams beim Deployment in Produktions- und sogar Testumgebungen, in denen echte Daten verwendet werden könnten, an der Einrichtung solcher Systeme beteiligt sein.

Um das Beispiel nachzuahmen, werden Sie nun selbst die beiden Server lokal ausführen. Im Arbeitsverzeichnis finden Sie einen Ordner namens data. Dort befindet sich die generierte CSV-Datei alice_id.csv mit den Identifikatoren:

env RUST_LOG=info cargo run --bin private-id-server --

--host 0.0.0.0:10009

--input data/alice_id.csv

--output data/alice_keys.csv

--no-tls

Die andere Partei führt denselben Befehl mit ihren Daten aus. Sie können den Vorgang jetzt simulieren, indem Sie beide über Ihren Localhost ausführen, wobei beide Server über Ihr lokales Netzwerk verbunden sind. Wenn Sie dies in einer Produktionsumgebung simulieren bzw. ausführen wollten, müssten Sie mehrere Rechner einrichten und ihnen erlauben, sich über TLS zu verbinden. Damit die Kommunikation weitergeleitet werden kann, müssen die Server miteinander verbunden und auffindbar sein.

Sobald Sie den Code ausführen, erhalten Sie eine Ausgabedatei, die an die von Ihnen angegebene Adresse gesendet wird. In dieser Datei befinden sich zwei Spalten: Eine enthält einen verschlüsselten Wert und die andere den Identifikator (ID). Für jede der Zeilen, in denen keine Übereinstimmung Ihrerseits gefunden wurde, enthält die ID-Spalte einen Nullwert. Das für dieses Beispiel verwendete Protokoll gibt alle verschlüsselten Nutzer-IDs wieder in derselben Reihenfolge zurück, was erforderlich ist, damit die spätere Berechnung mit den verschlüsselten Daten durchgeführt werden kann.

Jetzt bereitet jede Partei die Daten für die Encrypted Computation mit Moose vor, indem sie die in der von der Private-ID-Bibliothek generierten Datei gefundenen Übereinstimmungen verwendet. Dies geschieht über einen Abgleich der verschlüsselten IDs mit anderen Datenquellen und das Hinzufügen der für die Encrypted Computation erforderlichen Daten als zusätzliche Spalten. In der Praxis lässt sich dies über eine Datei, in SQL oder in Python bewerkstelligen. In diesem Beispiel werden Sie auch eine zusätzliche Spalte erstellen, die einen booleschen Wert enthält, der angibt, ob die ID in Ihrem System existiert. Diese Spalte basiert auf der von der Private-ID-Bibliothek generierten Datei.

Nun können Sie Ihre Berechnungen mit Moose erstellen. Dazu können Sie, wie bereits erwähnt, eine NumPy-ähnliche Schnittstelle verwenden, die im pyMoose-Paket enthalten ist. Sehen wir uns an, wie die Syntax für Ihre Berechnungen aufgebaut ist:

import pymoose as pm

FIXED = pm.fixed(14, 23)

alice = pm.host_placement(name="alice")

bob = pm.host_placement(name="bob")

carole = pm.host_placement(name="carole")

rep = pm.replicated_placement(name="rep", players=[alice, bob, carole])

mirrored = pm.mirrored_placement(name="mirrored", players=[alice, bob, carole])

Zu Beginn der Berechnung legen Sie eine Festkommazahl fest. Als Voreinstellung wird eine Genauigkeit von 14 Ganzzahlen und 23 Dezimalstellen vorgeschlagen. Je nachdem, wie Ihre Gegebenheiten sind und Ihre Daten es erfordern, können Sie diese Werte noch erhöhen oder verringern.

Als Nächstes richten Sie mehrere Platzhalter ein, die jeweils einen Spieler in Ihrer Berechnung repräsentieren. Da Moose ein Replicated Secret Sharing verwendet (um Multiplikation und Division zu unterstützen), benötigen Sie drei Platzhalter, die hier als Alice, Bob und Carole bezeichnet werden. Um dann die replizierten bzw. verschlüsselten Platzhalter in der Berechnung zu definieren, übergeben Sie diese Akteure an den Parameter players. Hier verwenden Sie auch ein sogenanntes mirrored Placement, das es Ihnen ermöglicht, Konstanten im Klartext für die Verwendung in lokalen oder replizierten Operationen gemeinsam zu nutzen:

@pm.computation

def psi_and_agg():

with alice:

x_a = pm.load("x_a", dtype=pm.float64)

user_id_available_a = pm.load("user_id_available_a", dtype=pm.bool_)

Anschließend können Sie Ihre Encrypted Computation mit dem Dekorator @pm.computation versehen. In der Regel empfiehlt es sich, die Berechnung als eine einzelne große Funktion zu definieren und dabei die Namensräume zu verwenden, die Sie zuvor erstellt haben, um festzulegen, welche Spieler welche Schritte ausführen. Das dient der Transparenz und stellt sicher, dass alle Spieler verstehen, was berechnet wird und wo die Berechnungen durchgeführt werden. Wenn Sie die Berechnung in kleinere Funktionen mit Unittests aufteilen möchten oder müssen, können Sie dies mittels nicht dekorierter Funktionen tun und diese Funktionen dann in der dekorierten Funktion einsetzen.

Im vorliegenden Beispielcode werden die Daten geladen und in Festkommawerte konvertiert. Hierfür können Sie die load-Methode der pyMoose-Bibliothek nutzen, bei der der zu verwendende NumPy-Datentyp (dtype) (https://oreil.ly/G7K-s) und ein Festkommawert deklariert werden müssen:

with bob:

x_b = pm.load("x_b", dtype=pm.float64)

user_id_available_b = pm.load("user_id_available_b", dtype=pm.bool_)

# Berechnet logisches UND zwischen user_id_available von Alice und Bob.

# Wenn 1 zurückgegeben wird, bedeutet dies, dass die User-ID in den

# Datensätzen von Alice und Bob enthalten war.

exist_in_alice_and_bob_bool = pm.logical_and(

user_id_available_a, user_id_available_b

)

# Filtert Bobs Daten, um nur die Einträge beizubehalten, bei denen

# exist_in_alice_and_bob_bool den Wert 1 zurückgegeben hat.

x_b_sub = pm.select(x_b, axis=0, index=exist_in_alice_and_bob_bool)

x_b_sub = pm.cast(x_b_sub, dtype=FIXED)

with alice:

# Filtert Daten von Alice, um nur die Einträge beizubehalten, bei

# denen exist_in_alice_and_bob_bool den Wert 1 zurückgegeben hat.

x_a_sub = pm.select(x_a, axis=0, index=exist_in_alice_and_bob_bool)

x_a_sub = pm.cast(x_a_sub, dtype=FIXED)

Für Bob führen Sie diese Vorbereitungen ebenfalls durch und berechnen dann auf Basis der booleschen Spalten der einzelnen Spieler mittels einer logischen UND-Operation die Schnittmenge zwischen den Mengen. Da die Private-ID-Bibliothek die gleichen verschlüsselten IDs an jeden Spieler in der gleichen Reihenfolge zurückgegeben hat, bestätigt dies, dass alle Zeilen korrekt übereinstimmen. Sobald beide nur noch die Schnittmenge ihrer Datensätze haben, können Sie die eigentliche Berechnung durchführen:

with mirrored:

ten_percent = pm.constant(0.1, dtype=FIXED)

with rep:

# Aggregierung: Durchschnittlicher Quotient

# der Summe von x_a_sub & x_b_sub

spend_per_category = x_a_sub + x_b_sub

spend_per_user = pm.sum(spend_per_category, axis=1)

category_percent = spend_per_category / pm.expand_dims(spend_per_user, axis=1)

res = pm.greater(category_percent, ten_percent)

with alice:

res = pm.cast(res, dtype=pm.float64)

res = pm.save("agg_result", res)

return res

Zunächst erstellen Sie eine Klartext-Konstante mit dem Wert 0,1, deren Spiegelzahl mit allen Teilnehmern geteilt wird. Diese wird später verwendet, um die Privatsphäre der Nutzerinnen und Nutzer und die Geheimhaltung der Ergebnisse zu wahren.

In der eigentlichen Berechnung wird dann der replizierte Namensraum verwendet. Innerhalb dieses Namensraums sind alle Daten und Berechnungen verschlüsselt. Die pyMoose-Bibliothek bietet ähnliche Funktionen wie NumPy und unterstützt zahlreiche ndarray-Operationen. Der Hauptunterschied besteht darin, dass diese Berechnungen in Rust und im Rahmen von verschlüsselten Protokollen in einem Ring ausgeführt werden!

Hier verwenden Sie gewöhnliche vektorisierte Operationen wie bei NumPy und berechnen die Ausgaben pro Kategorie, die Gesamtausgaben pro Nutzer und dann den prozentualen Anteil der Ausgaben pro Nutzer innerhalb jeder Kategorie. Es wird ein boolesches Ergebnis zurückgegeben, bei dem für jede Kategorie eine 1 ausgegeben wird, wenn die Ausgaben mehr als 10 % der Gesamtausgaben ausmachen. So bleibt einerseits die Privatsphäre der Nutzer gewahrt, andererseits sind die Überschneidungen aber dennoch aufschlussreich. Sie können diesen Wert natürlich je nach Bedarf an die Anforderungen der jeweiligen Geschäftspartner oder Produkte anpassen.

Am Ende dieser speziellen Berechnung erhält nur Alice die Ergebnisse und kann sie in Gleitkommawerte zurückkonvertieren, um sie auf ihrem Computer zu speichern. Wenn Sie möchten, dass beide Parteien das Ergebnis erhalten, würden Sie einen weiteren Codeblock definieren, der es Bob ermöglicht, das Ergebnis ebenfalls zu erhalten.

Nachdem die Berechnung vollständig definiert ist, können Sie sie – sofern Sie Moose bereits installiert haben – nun ausführen. Bei Moose werden die Berechnungen ebenfalls mit Rust durchgeführt:

executors_storage = {

"alice": {"x_a": x_a, "key_a": key_a},

"bob": {"x_b": x_b, "key_b": key_b},

}

runtime = pm.LocalMooseRuntime(

identities=["alice", "bob", " carole"],

storage_mapping=executors_storage,

)

runtime.set_default()

_ = psi_and_agg()

Eine Installationsanleitung finden Sie im Repository des Moose-Frameworks (https://oreil.ly/ih1lw).

Damit Sie die Berechnung in Python ausführen können, müssen Sie zunächst ein Dictionary definieren, das den jeweiligen Speicherort der Inputdaten der einzelnen Parteien angibt. Moose unterstützt derzeit CSV- und NumPy-Dateien, die mühelos aus Pandas- oder NumPy-Objekten erstellt werden können. Um die lokalen Executors und die Laufzeit zu starten, müssen Sie lediglich die Spieler anlegen, den Speicherort ihrer Daten angeben und dann die set_default-Methode aufrufen, um die Laufzeit zu starten.

Sobald Sie diese Zelle des im Repository des Buchs befindlichen Jupyter Notebook ausführen, wird die Berechnung durchgeführt, und das endgültige Ergebnis wird ausgegeben, da es im Rahmen der Berechnung durch die return-Anweisung zurückgegeben wird. Das Ergebnis können Sie mit der Klartextausgabe in der folgenden Zelle vergleichen und sich vergewissern, dass die Werte übereinstimmen.

Bei dieser Berechnung wird jeder Prozess der einzelnen Platzhalter auf Ihrem eigenen Computer als separater Prozess ausgeführt, wodurch sich das Testen und Debuggen leichter gestaltet. Im Fall einer echten Encrypted Computation müssten sie allerdings verteilt werden. In der Dokumentation von PyMoose (https://oreil.ly/MnvNP) finden Sie eine Anleitung dazu, wie Sie mehrere Spieler anlegen und das Netzwerk zwischen den verschiedenen Hosts einrichten können.

Beim Betrieb in einer Produktionsumgebung müssen Sie sicherstellen, dass die Hosts strategisch so günstig wie möglich platziert sind, um Latenzzeiten und Datenübertragungskosten möglichst gering zu halten. Wenn z.B. alle Spieler in einer bestimmten Cloud angesiedelt sind, wäre es gut, dasselbe Cloud-Netzwerk und wenn möglich dieselbe Region zu verwenden. Dadurch würden die Berechnungen schneller vonstattengehen, was insbesondere bei größeren und aufwendigen Berechnungen – wie dem Training eines Modells – von Bedeutung ist.

image

Wenn Sie eine Reihe unterschiedlicher Protokolle verwenden oder testen möchten, sollten Sie auch einen Blick auf andere verfügbare MPC- und HE-Bibliotheken werfen. Ich empfehle Ihnen, die gut gepflegten GitHub-Repositories awesome-mpc (https://oreil.ly/6DAM-) und awesome-he (https://oreil.ly/BnuHX) im Auge zu behalten, damit Sie stets einen aktuellen Überblick über die besten verfügbaren Frameworks, Bibliotheken und Protokolle haben. Ich kann auch das CarbyneStack-Projekt (https://oreil.ly/gcnm5) von Bosch Research empfehlen, das darauf abzielt, die Einrichtung und Verwendung von MPC-Protokollen für Softwareentwickler zu vereinfachen.

Ehe der Code ausgeführt wird, kompiliert der Compiler von Moose Ihre in Python formulierte High-Level-Darstellung in eine Low-Level-Darstellung. Dafür sind mehrere Durchläufe vorgesehen. Bei jedem dieser Durchläufe kann die Berechnung von einer oder mehreren beteiligten Parteien inspiziert werden, sodass diese überprüfen können, ob die Protokolle und der Plan wie erwartet funktionieren.

Abbildung 7-3 vermittelt Ihnen einen Eindruck davon, wie das im Fall eines einfachen Berechnungsgraphen für ein Skalarprodukt aussieht, wobei alle kryptografischen Protokolle und Netzwerkaktivitäten ebenfalls dargestellt sind. Wenn Sie noch tiefer in den Graph hineinzoomen oder erfahren möchten, wie Sie Ihre eigenen Graphen visualisieren können, besuchen Sie das Moose-Repository, in dem ein Beispiel zur Grapherstellung (https://oreil.ly/kTmq-) enthalten ist.

Künftig werden Compiler wie Moose in der Lage sein, Berechnungen auch hinsichtlich bestimmter Datenschutz- und Geheimhaltungsgarantien sowie hinsichtlich der Performance zu optimieren.

image

Wenn Sie wissen wollen, wie sich mit MPC und HE Vorhersagen unter Wahrung der Privatsphäre treffen lassen (private Inference) – d.h., das Modell und die Werte bleiben verschlüsselt –, empfehle ich Ihnen, einen Blick auf das Notebook von Zama und Hugging Face (https://oreil.ly/pVPxs) sowie das im Blogbeitrag von Yann Dupis vorgestellte Notebook zur Nutzung der Moose- und Hugging-Face-Bibliothek (https://oreil.ly/K49M7) zu werfen. Da beide Bibliotheken NumPy-ähnlichen Code unterstützen, gibt es noch viel Potenzial, diese Anwendungsfälle zu nutzen und zu erweitern.

image

Abbildung 7-3: Moose-Kompilierungsgraph – von High-Level zu Low-Level

Vision einer Welt mit sicherem Datenaustausch

Ich hoffe, dieses Kapitel hat Sie dazu angeregt, darüber nachzudenken, wie Encrypted Computation im Rahmen realer Problemstellungen in der Data Science helfen kann. Encrypted Computation ist die inspirierendste Technologie meiner Karriere – und etwas, von dem ich fest überzeugt bin, dass es die Art des Datenaustauschs, wie wir ihn kennen, verändern kann und wird.

Heutzutage tauschen Unternehmen große Datenmengen in Form von Klartext aus und treffen komplexe Vereinbarungen über die gemeinsame Nutzung ihrer Daten, durch die versucht wird, Nutzung, Replikation und Aufbewahrungszeitraum rechtlich einzuschränken. Auch wenn rechtliche Verpflichtungen grundsätzlich begrüßenswert sind, lassen sie sich nie vollständig durchsetzen. Wie Sie vielleicht aus eigener Erfahrung wissen, ist es durchaus gängige Praxis, Daten von Drittanbietern mit Kerndaten des Unternehmens zu kombinieren. Ohne strenge Data-Lineage- und Governance-Systeme, die über formal validierte Regeln und Technologien zur Verbesserung des Datenschutzes verfügen, ist es schwierig, sicherzustellen, dass die gemeinsam genutzten Daten den rechtlichen Vereinbarungen und strengen Maßnahmen zum Schutz der Privatsphäre und zur Wahrung der Geheimhaltung genügen.

Encrypted Computation – insbesondere in Bereichen wie MPC – ermöglicht Ihnen, Data Science mit akkuraten Ergebnissen in einer gemeinsamen Umgebung durchzuführen, aber die Daten gleichzeitig besser zu schützen und vertraulich zu handhaben. Anstatt Daten Dritter zu speichern, sorgt sie für eine sichere und verschlüsselte Verarbeitung, ohne dass dadurch die Genauigkeit beeinträchtigt wird. Statt auf vertragliche Verpflichtungen und juristische Formulierungen – die Sie möglicherweise nie lesen werden, aber dennoch verstehen müssen – können Sie sich auf effektive kryptografische Protokolle und Verfahren verlassen, mit denen die Sicherheit der Daten gewährleistet wird.

Berechnungen zu verteilen und sie auf verschlüsselte Weise durchzuführen – wie es MPC standardmäßig bietet –, eröffnet, wie in Kapitel 6 beschrieben, neue Möglichkeiten. Es fördert eine neue kollektive und kollaborative Nutzung von Daten, indem neue verteilte Wege geschaffen werden, auf denen extrem sensible Daten gemeinsam genutzt werden können und dennoch geheim bleiben. MPC basiert bereits auf einem gemeinschaftlichen und geteilten Verständnis von Vertrauen – einem Verständnis, das Menschen in der echten Welt als Bürgerinnen, Anwohner und Mitglieder einer Gemeinschaft bereits erleben. Bei den derzeitigen datenwissenschaftlichen Implementierungen wird dieses Vertrauen durch eine enorme Anhäufung von Daten auf einige wenige mächtige Parteien übertragen. Stattdessen könnte dieses Vertrauen nah an den Interessen und Wünschen der Nutzerinnen und Nutzer bleiben und so die nutzerorientierte Zusammenarbeit und Entwicklung von Berechnungen fördern, die den Nutzern direkt zugutekommen und einen positiven Beitrag zu ihrer Welt und der Gesellschaft leisten.

In Kombination mit Techniken wie Federated Analytics und verteilter Datenverarbeitung eröffnet Encrypted Computation neue Wege, mit denen sichergestellt werden kann, dass Daten geheim und geschützt bleiben und nur auf dem bevorzugten Speichersystem des Nutzers oder als Ergebnis einer vereinbarten Berechnung entschlüsselt werden. Dies kann die Art und Weise, wie Daten verarbeitet, gemeinsam genutzt und verwendet werden, grundlegend verändern und sicherstellen, dass bei Datenlecks in Unternehmen niemals private Details über Einzelpersonen an die Öffentlichkeit gelangen werden und dass die Verarbeitung nachweislich auf eine sichere und vertrauliche Weise erfolgt.

Zusammenfassung

In diesem Kapitel haben Sie die grundlegenden Protokolle und die wichtigsten kryptografischen Prinzipien für Encrypted Computation kennengelernt. Sie haben nun eine bessere Vorstellung von verschiedenen Anwendungsfällen, in denen Encrypted Computation hilfreich sein kann, wie etwa der gemeinsamen Nutzung, dem Einblick in und der Verarbeitung von Daten durch mehrere Parteien mit MPC oder der Verarbeitung und Rückleitung verschlüsselter Daten an den Nutzer zur Entschlüsselung mit HE. Darüber hinaus haben Sie sich mit verschiedenen Sicherheitsmodellen befasst, um besser zu verstehen, wie kryptografische Protokolle Nutzerinnen und Nutzern eine wirklich sichere Verarbeitung ihrer Daten bieten.

Sie haben auch einige reale Anwendungsfälle analysiert und nachvollzogen, wie Sie mit Open-Source-Bibliotheken wie Moose Ihre eigene verschlüsselte Datenverarbeitung aufbauen können. Ich hoffe, ich konnte Ihre Neugierde wecken und Ihnen zeigen, dass Verschlüsselung den Datenschutz und die Sicherheit im Rahmen von Data-Science-Anwendungen verbessern kann. In Kapitel 9 werden Sie ganzheitlicher über alle bisher behandelten Datenschutztechnologien nachdenken und herauszufinden, wie Sie Ihre Problemstellung angehen sollten, um die beste Lösung für Ihren Anwendungsfall zu finden. Zuvor aber werden Sie in Kapitel 8 in die rechtlichen Aspekte von Privacy eintauchen, damit Sie lernen, wie Sie Datenschutzrisiken beurteilen und die Anforderungen Ihres Unternehmens mit jenen des Gesetzes in Einklang bringen können.