Schlüsselsätze

Tink verwendet Schlüsselsätze, um die Schlüsselrotation zu ermöglichen. Formal ist ein Schlüsselsatz eine nicht leere Liste1 von Schlüsseln, in der ein Schlüssel als primär festgelegt ist (der Schlüssel, der z. B. 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 wichtigste Möglichkeit für Nutzer, auf Schlüssel zuzugreifen (über die Klasse KeysetHandle). So wird sichergestellt, dass jeder Nutzer Code hat, um mehrere Schlüssel gleichzeitig zu verarbeiten. Für die meisten Nutzer von Kryptografie ist die Verwaltung mehrerer Schlüssel eine Notwendigkeit: Es muss möglich sein, Schlüssel zu ändern (alte Schlüssel können beispielsweise offengelegt werden). Außerdem gibt es fast nie einen atomaren „Wechsel zum nächsten Schlüssel“, der global und sofort auf die Maschinen, auf denen der Code ausgeführt wird, und alle Chiffretexte angewendet werden kann. Daher muss der Nutzer Code schreiben, der funktioniert, wenn er von einem Schlüssel zum nächsten wechselt.

Beispiel: AEAD

Angenommen, Sie haben ein AEAD-Keyset, das mehrere Schlüssel für das AEAD-Primitive enthält. Wie bereits erwähnt, werden durch jeden Schlüssel zwei Funktionen eindeutig festgelegt: \(\mathrm{Enc}\) und \(\mathrm{Dec}\). Im Keyset werden jetzt auch zwei neue Funktionen angegeben: \(\mathrm{Enc}\) und \(\mathrm{Dec}\) . \(\mathrm{Enc}\) entspricht einfach der Funktion \(\mathrm{Enc}\) des Primärschlüssels des Keysets, während die Funktion \(\mathrm{Dec}\) versucht, mit allen Schlüsseln zu entschlüsseln. Dabei werden die Schlüssel in einer bestimmten Reihenfolge durchlaufen (siehe unten).

Schlüsselsätze sind vollständige Schlüssel, d. h., sie enthalten eine vollständige Beschreibung der verwendeten Funktionen \(\mathrm{Enc}\) und\(\mathrm{Dec}\) . Das bedeutet, dass Nutzer eine Klasse schreiben können, die als Eingabe ein KeysetHandle akzeptiert. 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 Folgendes kommunizieren: Um diese Klasse zu verwenden, müssen Sie mir die Beschreibung eines kryptografischen Primitivs zur Verfügung stellen.

Schlüsselrotation

Stellen Sie sich einen Tink-Nutzer vor, der ein Programm schreibt, das zuerst einen Keysets von einem KMS abruft, dann ein AEAD-Objekt aus diesem Keysets erstellt und schließlich dieses Objekt zum Ver- und Entschlüsseln von Chiffretexten verwendet.

Ein solcher Nutzer ist automatisch für die Schlüsselrotation vorbereitet und kann Algorithmen wechseln, falls die aktuelle Auswahl nicht mehr dem Standard entspricht.

Bei der Implementierung einer solchen Schlüsselrotation ist jedoch Vorsicht geboten: Zuerst sollte dem Keyset ein neuer Schlüssel hinzugefügt werden (aber noch nicht als primärer Schlüssel festgelegt werden). 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 das Keyset verwenden.

Wichtige Kennungen in Chiffretexten

Sehen wir uns noch einmal das Beispiel für ein AEAD-Keyset an. Wenn dies auf naive Weise geschieht, muss Tink versuchen, einen Geheimtext mit allen Schlüsseln im Schlüsselsatz zu entschlüsseln, da nicht bekannt ist, welcher Schlüssel zum Verschlüsseln des Schlüsselsatzes verwendet wurde. Das kann zu einem hohen Leistungsaufwand führen.

Aus diesem Grund ermöglicht Tink, Geheimtexte mit einem 5-Byte-String zu versehen, der aus der ID abgeleitet wird. Gemäß der oben beschriebenen Philosophie der „Full Keys“ ist dieses Präfix Teil des Schlüssels und alle Chiffretexte, 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 Keysets befindet, berechnet Tink dieses Tag aus der ID, die der Schlüssel im Keyset hat. Da 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, bedeutet dies auch, dass der Schlüssel nur in einem Schlüsselsatz enthalten sein kann, wenn er eine bestimmte ID hat. Dies hat einige Auswirkungen auf die Beschreibung der Implementierung von Schlüsselobjekten in verschiedenen Sprachen.

Schlüssel mit ID-Anforderung, aber ohne Ausgabepräfix

Einige Schlüssel müssen eine bestimmte ID haben, fügen ihrer Ausgabe aber kein Präfix hinzu. Beispielsweise werden mit Signaturschlüsseln mit der NO_PREFIX_WITH_PREHASH_ID-Variante (gespeichert mit dem Ausgabepräfix-Typ WITH_ID_REQUIREMENT) Signaturen ohne Präfix erstellt. Wenn Sie einen solchen Schlüssel mit dem Prehash-Primitive verwenden, schreibt Tink die Schlüssel-ID in den Prehash-Wert, damit ein Remote-Signer weiß, mit welchem seiner Schlüssel er signieren soll.

Wie bei Schlüsseln mit einem Präfix kann ein solcher Schlüssel nur in einem Keyset unter dieser ID enthalten sein. Die Schlüssel-ID im Prehash-Wert ist wie das Ausgabepräfix nur ein Metadatenwert: Die Signatur bindet ihn nicht und Prüfer sehen ihn nie. Informationen zum Byte-Level-Layout finden Sie unter Tink-Wire-Format.


  1. In einigen Teilen von Tink werden Schlüsselsätze weiterhin als Set behandelt. Das sollte jedoch geändert werden. Der Grund dafür ist, dass die Reihenfolge im Allgemeinen wichtig ist. Sehen Sie sich beispielsweise den typischen Lebenszyklus einer Schlüsselrotation mit AEAD an. Zuerst wird einem Schlüsselsatz ein neuer Schlüssel hinzugefügt. Dieser Schlüssel ist noch nicht der primäre Schlüssel, aber er ist aktiv. Dieser neue Schlüsselsatz wird für alle Binärdateien eingeführt. Sobald alle Binärdateien den neuen Schlüssel kennen, wird er zum primären Schlüssel gemacht. Erst dann ist es sicher, ihn zu verwenden. Im zweiten Schritt muss die Schlüsselrotation den zuletzt hinzugefügten Schlüssel kennen. ↩

  2. Zur Kompatibilität mit einer internen Google-Bibliothek ermöglicht Tink, dass in Schlüsselsätzen IDs wiederholt werden. Diese Unterstützung wird in Zukunft entfernt. ↩