Tink verwendet Schlüsselsätze, um die Schlüsselrotation zu ermöglichen. Formell ist ein Schlüsselsatz eine nicht leere Liste1 von Schlüsseln, bei der ein Schlüssel als primärer Schlüssel festgelegt ist (der Schlüssel, der beispielsweise zum Signieren und Verschlüsseln neuer Klartexte verwendet wird). Außerdem erhalten Schlüssel in einem Schlüsselsatz eine eindeutige ID2 und einen Schlüsselstatus, mit dem Schlüssel deaktiviert werden können, ohne sie aus einem Schlüsselsatz zu entfernen.
Schlüsselsätze sind die Hauptmethode, mit der Nutzer über die Klasse KeysetHandle
auf Schlüssel zugreifen können. So hat jeder Nutzer Code, um mehrere Schlüssel gleichzeitig zu verarbeiten. Für die meisten Nutzer der Kryptografie ist die Verarbeitung mehrerer Schlüssel eine Notwendigkeit: Es muss möglich sein, Schlüssel zu ändern (alte Schlüssel können beispielsweise gehackt werden). Außerdem gibt es fast nie einen atomaren „Wechsel zum nächsten Schlüssel“, der global und sofort auf die Maschinen angewendet werden kann, auf denen der Code ausgeführt wird, und auf alle Geheimtexte. Daher muss der Nutzer Code schreiben, der funktioniert, wenn der Nutzer von einem Schlüssel zum nächsten wechselt.
Beispiel: AEAD
Angenommen, Sie haben ein AEAD-Schlüsselset mit mehreren Schlüsseln für die AEAD-Primitivfunktion. Wie bereits erwähnt, gibt jeder Schlüssel eindeutig zwei Funktionen an: \(\mathrm{Enc}\) und \(\mathrm{Dec}\). Der Schlüsselsatz enthält jetzt auch zwei neue Funktionen: \(\mathrm{Enc}\) und \(\mathrm{Dec}\) – \(\mathrm{Enc}\) entsprechen einfach der Funktion \(\mathrm{Enc}\) des Primärschlüssels des Schlüsselsatzes. Die Funktion \(\mathrm{Dec}\) versucht dagegen, mit allen Schlüsseln zu entschlüsseln, indem sie sie in einer bestimmten Reihenfolge durchgeht. Unten erfahren Sie, wie Tink die Leistung dabei verbessert.
Schlüsselsätze sind Vollschlüssel: Sie enthalten eine vollständige Beschreibung der verwendeten Funktionen \(\mathrm{Enc}\) und\(\mathrm{Dec}\) . Das bedeutet, dass Nutzer eine Klasse schreiben können, die eine KeysetHandle
als Eingabe nimmt. Damit wird ausgedrückt, dass die Klasse eine vollständige Beschreibung von Objekten \(\mathrm{Enc}\) und \(\mathrm{Dec}\) benötigt, um richtig zu funktionieren. So können Nutzer APIs schreiben, die mitteilen, dass für die Verwendung dieser Klasse die Beschreibung eines kryptografischen Primitives angegeben werden muss.
Schlüsselrotation
Angenommen, ein Tink-Nutzer schreibt ein Programm, das zuerst einen Schlüsselsatz von einem KMS abholt, dann aus diesem Schlüsselsatz ein AEAD-Objekt erstellt und schließlich dieses Objekt zum Verschlüsseln und Entschlüsseln von Geheimtexten verwendet.
Ein solcher Nutzer ist automatisch für die Schlüsselrotation und den Algorithmuswechsel gerüstet, falls die aktuelle Auswahl nicht mehr den Standards entspricht.
Bei der Implementierung einer solchen Schlüsselrotation ist jedoch etwas Vorsicht geboten: Zuerst sollte das KMS dem Schlüsselsatz einen neuen Schlüssel hinzufügen, ihn aber noch nicht als primären Schlüssel festlegen. Anschließend muss das neue Keyset für alle Binärdateien eingeführt werden, damit jede Binärdatei, die dieses Keyset verwendet, den neuesten Schlüssel im Keyset hat. Erst dann sollte der neue Schlüssel zum primären Schlüssel gemacht werden. Das resultierende Keyset wird dann wieder an alle Binärdateien verteilt, die es verwenden.
Schlüssel-IDs in Geheimtexten
Denken Sie noch einmal an das Beispiel für ein AEAD-Schlüsselsatz. Wenn dies naiv geschieht, muss Tink versuchen, den Geheimtext mit allen Schlüsseln im Schlüsselsatz zu entschlüsseln, da nicht bekannt ist, mit welchem Schlüssel der Schlüsselsatz verschlüsselt wurde. Das kann zu einem großen Leistungsoverhead führen.
Aus diesem Grund ermöglicht Tink, Geheimtexten ein Präfix aus einem 5-Byte-String hinzuzufügen, der von der ID abgeleitet ist. Gemäß der Philosophie der vollständigen Schlüssel oben ist dieses Präfix Teil des Schlüssels und alle Geheimtexte, die jemals mit diesem Schlüssel abgeleitet wurden, sollten dieses Präfix haben. Wenn Nutzer Schlüssel erstellen, können sie auswählen, ob der Schlüssel ein solches Präfix verwenden soll oder ob ein Geheimtextformat ohne Präfix verwendet werden soll.
Wenn sich ein Schlüssel in einem Schlüsselsatz befindet, berechnet Tink dieses Tag anhand der ID, die der Schlüssel im Schlüsselsatz hat. Da die IDs innerhalb eines Schlüsselsatzes eindeutig sind2, sind auch die Tags eindeutig. Wenn also nur getaggte Schlüssel verwendet werden, gibt es keinen Leistungsverlust im Vergleich zur Entschlüsselung mit einem einzelnen Schlüssel: Tink muss beim Entschlüsseln nur einen der Schlüssel ausprobieren.
Da das Tag jedoch Teil des Schlüssels ist, kann der Schlüssel nur dann in einem Schlüsselsatz enthalten sein, wenn er eine bestimmte ID hat. Das hat einige Auswirkungen auf die Beschreibung der Implementierung von Schlüsselobjekten in verschiedenen Sprachen.
-
In einigen Teilen von Tink werden Schlüsselsätze weiterhin als Set behandelt. Das sollte sich jedoch ändern. Der Grund dafür ist, dass die Reihenfolge im Allgemeinen wichtig ist: Betrachten Sie beispielsweise den typischen Lebenszyklus einer Schlüsselrotation mit Aead. Zuerst wird einem Schlüsselsatz ein neuer Schlüssel hinzugefügt. Dieser Schlüssel ist noch nicht als primär festgelegt, aber aktiv. Dieses neue Keyset wird für alle Binärdateien eingeführt. Sobald alle Binärdateien den neuen Schlüssel kennen, wird er zum primären Schlüssel. Erst dann ist die Verwendung dieses Schlüssels sicher. In diesem zweiten Schritt muss die Schlüsselrotation den zuletzt hinzugefügten Schlüssel kennen. ↩
-
Zur Kompatibilität mit einer internen Google-Bibliothek ermöglicht Tink Schlüsselsätze, in denen IDs wiederholt werden. Diese Unterstützung wird in Zukunft nicht weitergeführt. ↩