Das Noise Protokoll Framework dient als Open-Source-Framework für Verschlüsselungsprotokolle zum Ende-zu-Ende-verschlüsselten Datenaustausch, basierend auf dem Diffie-Hellman-Schlüsselaustausch (DH). Es wurden anhand des Frameworks bereits sichere Alternativen zum bekannten TLS erstellt, die die Integrität und Authentizität der übertragenen Nachrichten durch die Nutzung eines Verfahrens namens Authenticated Encryption with Additional Data (AEAD) gewährleistet.
Herkunft
Das Framework wurde von Trevor Perrin mit Unterstützung von Moxie Marlinspike entwickelt und wird bereits in dem bekannten Instant Messenger WhatsApp, dem Lightning-Netzwerk zur Skalierung der möglichen Bitcoin Transaktionen und dem VPN-Tunnel-System WireGuard verwendet. Weiterhin gibt es aktuell schon erste Entwürfe zum geplanten Noise-Socket, welcher als TLS-Socket für ein auf dem Framework aufgebautes Noise-Protokoll dienen soll.
Funktionsweise
Das Protokoll beginnt gleich wie bei TLS mit der Handshake-Phase, durch die die beiden Public-Keys der Parteien ausgetauscht werden. Die Schlüssel der beiden Parteien können flüchtig und/oder statisch sein. Infolgedessen wird durch die Durchführung einer Reihe von DH Operationen ein gemeinsamer Secret-Key berechnet, mit Hilfe dessen ein symmetrisches Verschlüsselungsverfahren genutzt werden kann und die Nachrichten zum Schutz der Authentizität durch einen Message Authentication Code (MAC) abgesichert werden. Beim Noise Protokoll Framework kann zwischen unterschiedlichen Handshaker-Pattern, DH Funktionen, Hash Funktionen und Verschlüsselungsfunktionen ausgewählt werden durch die man ein konkretes Noise Protokoll erhält.
Handshake
Der Kern des Noise Protokolls ist der jeweilige Satz an Variablen der Parteien zur Zeit des Handshakes und die Regeln des gewählten Handshake-Pattern nach denen die einzelnen Handshake-Nachrichten verarbeitet, gesendet und empfangen werden. Jede Partei hat folgende Variablen:
- s, e: Das lokale, statische und/oder flüchtige Schlüsselpaar, welches auch leer sein kann.
- rs, re: Das statische und/oder flüchtige Schlüsselpaar der Remote-Partei, welches auch leer sein kann.
- h: Ein Handshake-Hashwert der alle Handshakedaten hasht die gesendet oder empfangen werden.
- ck: Der Chaining-Key der alle vorhergehenden DH Ausgaben hasht. Sobald der Handshake abgeschlossen ist, wird der Chaining-Key zur Ableitung des Verschlüsselungsschlüssels verwendet.
- k, n: Der Verschlüsselungsschlüssel k, welcher auch leer sein kann und eine zählbasierte Nonce n, werden verwendet um die statischen Public-Keys und die Handshake-Payloads mit Hilfe von AEAD, welches h als AD nutzt, zu verschlüsseln. Immer wenn durch die DH Ausgabe ein neuer ck berechnet wird, wird auch ein neuer k berechnet.
Eine Handshake Nachricht besteht immer aus einem DH Public-Key gefolgt von einer frei, je nach Applikation, gewählten Payload. Der Sender stellt die jeweilige Nachricht, je nach Nachrichtenmuster, schrittweise aus Token zusammen. Möglichen Token sind:
- "e": Der Sender generiert einen neuen flüchtiges Schlüsselpaar und schreibt den Public-Key als Klartext in den Nachrichtenbuffer und hasht den Public-Key gemeinsam mit dem alten h um ein neues h abzuleiten.
- "s": Der Sender schreibt seinen statischen Public-Key von s in den Nachrichtenbuffer, verschlüsselt ihn mit k, falls k bereits generiert wurde und hasht den Public-Key gemeinsam mit dem alten h um ein neues h abzuleiten.
- "ee", "se", "es", "ss": Ein Diffie-Hellman zwischen dem Schlüsselpaar des Initiators und des Responders wird durchgeführt, das Ergebnis wird gemeinsam mit dem alten Chaining-Key ck gehasht um einen neuen ck und einen neuen h abzuleiten und abschließend wird noch n auf null gesetzt.
Nachdem der letzte Token einer Handshake-Nachricht verarbeitet wurde, schreibt der Sender noch die Payload in den Nachrichtenbuffer, verschlüsselt die Nachricht falls schon ein Verschlüsselungsschlüssel k generiert wurde und hasht die Ausgabe mit dem alten h um ein neues h abzuleiten.
Beispiele
Handshake-Pattern eines Handshakes ohne Authentifizierung:
-> e <- e, ee
- Der Initiator versendet die erste Nachricht mit seinem flüchtigen Public-Key.
- Der Responder sendet seinen eigenen flüchtigen Public-Key zurück.
- Abschließend wird ein DH durchgeführt und die Ausgabe wird zu einem Secret-Key gehasht.
Handshake-Pattern eines Handshakes mit Authentifizierung des Responders:
-> e <- e, ee, s, es
In diesem Fall sind die endgültigen ck und k Werte ein Hash beider DH Ergebnisse. Da man anhand der Token erkennt, dass ein DH zwischen dem flüchtigen Schlüsselpaar des Initiators und dem statischen Schlüsselpaar des Responders durchgeführt wurde. Kann der Initiator die Payload der zweiten Nachricht entschlüsseln, wurde der Responder erfolgreich authentifiziert.
Handshake-Pattern eines Handshakes mit Authentifizierung des Initiators:
-> e <- e, ee, s, es -> s, se
Dies wird auf dieselbe Weise wie die Authentifizierung des Responders durchgeführt.
Es gibt noch eine Vielzahl an mögliche Patterns aus denen ausgewählt werden kann, die immer je nach Anwendungsbereich ausgewählt werden.
Eigenschaften
Das Noise-Protokoll-Framework ist kompatibel mit verschiedenen Verschlüsselungs- und Hashmethoden.
Folgende Verschlüsselungsverfahren werden unterstützt:
- Advanced Encryption Standard (AES) im Betriebsmodus Galois/Counter Mode (GCM)
- ChaCha20-Poly1305
Folgende Hashverfahren werden unterstützt:
- SHA256
- SHA512
- BLAKE2s
- BLAKE2b
Folgende Diffie-Hellman-Funktionen werden unterstützt:
- Curve25519
- Curve448
- NewHope