Überblick
Dieser Vorschlag baut auf den Änderungen des Vorschlags 152: ECIES Tunnels auf und erfordert diese.
Nur Tunnel, die durch Hops aufgebaut werden, die das BuildRequestRecord-Format für ECIES-X25519-Tunnel unterstützen, können diese Spezifikation implementieren.
Diese Spezifikation erfordert das Tunnel Build Options-Format, um den Typ der Tunnel-Schicht-Verschlüsselung anzuzeigen und Layer-AEAD-Schlüssel zu übertragen.
Ziele
Die Ziele dieses Vorschlags sind:
- Ersetzen von AES256/ECB+CBC durch ChaCha20 für etablierte Tunnel-IV und Layer-Verschlüsselung
- Verwendung von ChaCha20-Poly1305 für AEAD-Schutz zwischen den Hops
- Unsichtbarkeit von bestehender Tunnel-Schicht-Verschlüsselung für Nicht-Tunnel-Teilnehmer
- Keine Änderungen an der Gesamtlänge der Tunnel-Nachricht
Verarbeitung von etablierten Tunnel-Nachrichten
Dieser Abschnitt beschreibt Änderungen an:
- Ausgangs- und Eingangsgateway-Vorverarbeitung + Verschlüsselung
- Teilnehmer-Verschlüsselung + Nachverarbeitung
- Ausgangs- und Eingangsendpunkt-Verschlüsselung + Nachverarbeitung
Für einen Überblick über die aktuelle Tunnel-Nachrichtenverarbeitung siehe die Tunnel Implementation Spezifikation.
Besprochen werden nur Änderungen für Router, die die ChaCha20-Schicht-Verschlüsselung unterstützen.
Es werden keine Änderungen für gemischte Tunnel mit AES-Schicht-Verschlüsselung in Betracht gezogen, bis ein sicheres Protokoll entwickelt werden kann, um eine 128-Bit-AES-IV in einen 64-Bit-ChaCha20-Nonce umzuwandeln. Bloomfilter gewährleisten die Einzigartigkeit für die volle IV, aber die erste Hälfte einzigartiger IVs könnte identisch sein.
Dies bedeutet, dass die Schicht-Verschlüsselung für alle Hops im Tunnel einheitlich sein muss und während des Tunnel-Erstellungsprozesses mithilfe von Tunnel-Build-Optionen festgelegt wird.
Alle Gateways und Tunnel-Teilnehmer müssen einen Bloomfilter pflegen, um die beiden unabhängigen Nonces zu validieren.
Der in diesem Vorschlag erwähnte nonceKey ersetzt den in der AES-Schicht-Verschlüsselung verwendeten IVKey. Er wird mit dem gleichen KDF aus Vorschlag 152 erzeugt.
AEAD-Verschlüsselung von Hop-zu-Hop-Nachrichten
Für jedes Paar aufeinanderfolgender Hops muss ein zusätzlicher einzigartiger AEADKey generiert werden. Dieser Schlüssel wird von aufeinanderfolgenden Hops verwendet, um die innerlich ChaCha20-verschlüsselte Tunnel-Nachricht mit ChaCha20-Poly1305 zu verschlüsseln und zu entschlüsseln.
Die Tunnel-Nachrichten müssen die Länge des inneren verschlüsselten Rahmens um 16 Bytes reduzieren, um dem Poly1305 MAC Platz zu bieten.
AEAD kann nicht direkt auf die Nachrichten angewendet werden, da von ausgehenden Tunneln eine iterative Entschlüsselung benötigt wird. Iterative Entschlüsselung kann nur, so wie sie jetzt verwendet wird, mit ChaCha20 ohne AEAD erreicht werden.
+----+----+----+----+----+----+----+----+
| Tunnel ID | tunnelNonce |
+----+----+----+----+----+----+----+----+
| tunnelNonce cont. | obfsNonce |
+----+----+----+----+----+----+----+----+
| obfsNonce cont. | |
+----+----+----+----+ +
| |
+ Encrypted Data +
~ ~
| |
+ +----+----+----+----+
| | Poly1305 MAC |
+----+----+----+----+ +
| |
+ +----+----+----+----+
| |
+----+----+----+----+
Tunnel ID :: `TunnelId`
4 Bytes
die ID des nächsten Hops
tunnelNonce ::
8 Bytes
der Tunnel-Schicht-Nonce
obfsNonce ::
8 Bytes
der Nonce der Tunnel-Schicht-Verschlüsselung
Encrypted Data ::
992 Bytes
die verschlüsselte Tunnel-Nachricht
Poly1305 MAC ::
16 Bytes
Gesamtgröße: 1028 Bytes
Innere Hops (mit vor- und nachfolgenden Hops) haben zwei AEADKeys, einen zum Entschlüsseln der AEAD-Schicht des vorherigen Hops und einen zum Verschlüsseln der AEAD-Schicht zum folgenden Hop.
Alle internen Hop-Teilnehmer erhalten somit 64 zusätzliche Bytes an Schlüsseldaten in ihren BuildRequestRecords.
Das Ausgangs-Endpunkt und das Eingangs-Gateway benötigen nur zusätzliche 32 Bytes an Schlüsseldaten, da sie keine Nachrichten zwischen sich auf Tunnel-Schicht verschlüsseln.
Das Ausgangs-Gateway erzeugt seinen outAEAD-Schlüssel, der derselbe ist wie der inAEAD-Schlüssel des ersten ausgehenden Hops.
Der Eingangs-Endpunkt erzeugt seinen inAEAD-Schlüssel, der derselbe ist wie der outAEAD-Schlüssel des letzten eingehenden Hops.
Innere Hops erhalten einen inAEADKey und einen outAEADKey, die verwendet werden, um eingehende Nachrichten zu AEAD-entschlüsseln und ausgehende Nachrichten zu verschlüsseln.
Als Beispiel in einem Tunnel mit inneren Hops OBGW, A, B, OBEP:
- A’s
inAEADKeyist derselbe wie deroutAEADKeydes OBGW - B’s
inAEADKeyist derselbe wie A’soutAEADKey - B’s
outAEADKeyist derselbe wie OBEP’sinAEADKey
Schlüssel sind eindeutig für Hop-Paare, daher wird OBEP’s inAEADKey anders sein als A’s inAEADKey, A’s outAEADKey anders als B’s outAEADKey usw.
Verarbeitung von Gateway- und Tunnel-Erstellernachrichten
Gateways fragmentieren und bündeln Nachrichten auf die gleiche Weise und reservieren Platz nach den Instruktions-Fragmentrahmen für den Poly1305 MAC.
Innere I2NP-Nachrichten, die AEAD-Rahmen (einschließlich des MAC) enthalten, können über Fragmente verteilt werden, aber jede verlorene Fragmente führen zur fehlgeschlagenen AEAD-Entschlüsselung (fehlgeschlagene MAC-Verifizierung) am Endpunkt.
Gateway-Vorverarbeitung & Verschlüsselung
Wenn Tunnel die ChaCha20-Schicht-Verschlüsselung unterstützen, erzeugen Gateways zwei 64-Bit-Nonces pro Nachrichtensatz.
Eingehende Tunnel:
Verschlüsseln den IV und die Tunnel-Nachricht(en) mit ChaCha20
Verwenden 8-Byte
tunnelNonceundobfsNonceaufgrund der Lebensdauer der TunnelVerwenden einen 8-Byte
obfsNoncefür dietunnelNonce-VerschlüsselungZerstören den Tunnel, bevor 2^(64 - 1) - 1 Nachrichtensätze erreicht werden: 2^63 - 1 = 9.223.372.036.854.775.807
- Nonce-Limit, um Kollisionen der 64-Bit-Nonces zu vermeiden
- Nonce-Limit nahezu unmöglich zu erreichen, da dies über ~15.372.286.728.091.294 Nachrichten/Sekunde für 10-Minuten-Tunnel bedeuten würde
Den Bloomfilter basierend auf einer vernünftigen Anzahl erwarteter Elemente abstimmen (128 msgs/sec, 1024 msgs/sec? TBD)
Das Eingangs-Gateway (IBGW) des Tunnels verarbeitet Nachrichten, die von einem anderen Tunnel-Ausgangs-Endpunkt (OBEP) empfangen wurden.
Zu diesem Zeitpunkt ist die äußerste Nachrichtenschicht mit Transportverschlüsselung Punkt-zu-Punkt verschlüsselt. Die I2NP-Nachrichtenheader sind auf der Tunnel-Schicht für den OBEP und IBGW sichtbar. Die inneren I2NP-Nachrichten sind in Garlic-Klaven verpackt, die mithilfe von End-zu-Ende-Sitzungsverschlüsselung verschlüsselt sind.
Das IBGW verarbeitet die Nachrichten zu den entsprechend formatierten Tunnel-Nachrichten vor und verschlüsselt sie wie folgt:
// IBGW generiert zufällige Nonces, die keine Kollision in ihrem Bloom-Filter für jeden Nonce sicherstellen
tunnelNonce = Random(len = 64-bits)
obfsNonce = Random(len = 64-bits)
// IBGW ChaCha20 "verschlüsselt" jede der vorverarbeiteten Tunnel-Nachrichten mit ihrem tunnelNonce und layerKey
encMsg = ChaCha20(msg = tunnel msg, nonce = tunnelNonce, key = layerKey)
// ChaCha20-Poly1305 verschlüsselt jeden verschlüsselten Datenrahmen der Nachricht mit dem tunnelNonce und outAEADKey
(encMsg, MAC) = ChaCha20-Poly1305-Encrypt(msg = encMsg, nonce = tunnelNonce, key = outAEADKey)
Das Format der Tunnel-Nachrichten wird sich leicht ändern, indem zwei 8-Byte-Nonces anstelle einer 16-Byte-IV verwendet werden.
Der für die Verschlüsselung des Nonce verwendete obfsNonce wird dem 8-Byte tunnelNonce angehängt und wird von jedem Hop mithilfe des verschlüsselten tunnelNonce und dem nonceKey des Hops verschlüsselt.
Nachdem der Nachrichtensatz für jeden Hop vorab entschlüsselt wurde, verschlüsselt das Ausgangs-Gateway
die verschlüsselten Teile jeder Tunnel-Nachricht mit ChaCha20-Poly1305 AEAD unter Verwendung des tunnelNonce und seines outAEADKey.
Ausgehende Tunnel:
- Iterativ entschlüsseln Tunnel-Nachrichten
- ChaCha20-Poly1305 verschlüsseln vorzeitig entschlüsselte Tunnel-Nachrichten verschlüsselte Rahmen
- Verwenden die gleichen Regeln für Schicht-Nonces wie eingehende Tunnel
- Generieren zufällige Nonces einmal pro Satz gesendeter Tunnel-Nachrichten
// Für jeden Satz Nachrichten, generiere einzigartige, zufällige Nonces
tunnelNonce = Random(len = 64-bits)
obfsNonce = Random(len = 64-bits)
// Für jeden Hop, ChaCha20 den vorherigen tunnelNonce mit dem IV-Schlüssel des aktuellen Hops
tunnelNonce = ChaCha20(msg = prev. tunnelNonce, nonce = obfsNonce, key = hop's nonceKey)
// Für jeden Hop, ChaCha20 "entschlüsseln" die Tunnel-Nachricht mit dem aktuellen tunnelNonce und layerKey des Hops
decMsg = ChaCha20(msg = tunnel msg(s), nonce = tunnelNonce, key = hop's layerKey)
// Für jeden Hop, ChaCha20 "entschlüsseln" den obfsNonce mit dem verschlüsselten tunnelNonce und nonceKey des aktuellen Hops
obfsNonce = ChaCha20(msg = obfsNonce, nonce = tunnelNonce, key = hop's nonceKey)
// Nach der Hop-Verarbeitung, ChaCha20-Poly1305 verschlüsseln jede Tunnel-Nachrichts "entschlüsselte" Datenrahmen mit dem ersten verschlüsselten tunnelNonce und inAEADKey des Hops
(encMsg, MAC) = ChaCha20-Poly1305-Encrypt(msg = decMsg, nonce = first hop's encrypted tunnelNonce, key = first hop's inAEADKey / GW outAEADKey)
Teilnehmerverarbeitung
Teilnehmer werden wie bisher gesehene Nachrichten mit abklingenden Bloom-Filtern verfolgen.
Tunnel-Nonces müssen pro Hop einmal verschlüsselt werden, um Bestätigungsangriffe durch nicht aufeinanderfolgende, kolludierende Hops zu verhindern.
Hops werden den empfangenen Nonce verschlüsseln, um Bestätigungsangriffe zwischen vorherigen und nachfolgenden Hops zu verhindern, sodass kolludierende, nicht-aufeinanderfolgende Hops nicht erkennen können, dass sie zum gleichen Tunnel gehören.
Um den erhaltenen tunnelNonce und obfsNonce zu validieren, überprüfen Teilnehmer jeden Nonce einzeln auf Duplikate in ihrem Bloomfilter.
Nach der Validierung:
- ChaCha20-Poly1305 entschlüsselt jede Tunnel-Nachrichts AEAD-Verschlüsselungs-Frame mit dem erhaltenen
tunnelNonceund ihreminAEADKey - ChaCha20 verschlüsselt den
tunnelNoncemit ihremnonceKeyund dem erhaltenenobfsNonce - ChaCha20 verschlüsselt den verschlüsselten Datenrahmen jeder Tunnel-Nachricht mit dem verschlüsselten
tunnelNonceund ihremlayerKey - ChaCha20-Poly1305 verschlüsselt den verschlüsselten Datenrahmen jeder Tunnel-Nachricht mit dem verschlüsselten
tunnelNonceund ihremoutAEADKey - ChaCha20 verschlüsselt den
obfsNoncemit ihremnonceKeyund dem verschlüsseltentunnelNonce - Sendet das Tupel {
nextTunnelId, encrypted (tunnelNonce||obfsNonce), AEAD ciphertext || MAC} an den nächsten Hop.
// Zur Überprüfung sollten Tunnel-Hops den Bloom-Filter auf die Einzigartigkeit jedes empfangenen Nonce überprüfuntion
// Nach der Verifizierung die AEAD-Frame(s) durch ChaCha20-Poly1305-Entschlüsselung jeder Tunnel-Nachricht's verschlüsseltem Frame
// mit dem erhaltenen tunnelNonce und inAEADKey auspacken
encTunMsg = ChaCha20-Poly1305-Decrypt(msg = received encMsg \|\| MAC, nonce = received tunnelNonce, key = inAEADKey)
// ChaCha20 verschlüsseln den tunnelNonce mit dem obfsNonce und dem nonceKey des Hops
tunnelNonce = ChaCha20(msg = received tunnelNonce, nonce = received obfsNonce, key = nonceKey)
// ChaCha20 verschlüsseln jeden verschlüsselten Datenrahmen der Tunnel-Nachricht mit dem verschlüsselten tunnelNonce und dem layerKey des Hops
encMsg = ChaCha20(msg = encTunMsg, nonce = tunnelNonce, key = layerKey)
// Für AEAD-Schutz, zusätzlich ChaCha20-Poly1305 verschlüsseln jeden verschlüsselten Datenrahmen der Nachricht
// mit dem verschlüsselten tunnelNonce und dem outAEADKey des Hops
(encMsg, MAC) = ChaCha20-Poly1305-Encrypt(msg = encMsg, nonce = tunnelNonce, key = outAEADKey)
// ChaCha20 verschlüsseln den empfangenen obfsNonce mit dem verschlüsselten tunnelNonce und dem nonceKey des Hops
obfsNonce = ChaCha20(msg = obfsNonce, nonce = tunnelNonce, key = nonceKey)
Verarbeitung des Eingangs-Endpunkts
Für ChaCha20-Tunnel wird das folgende Schema zur Entschlüsselung jeder Tunnel-Nachricht verwendet:
- Validieren des empfangenen
tunnelNonceundobfsNonceunabhängig gegen ihren Bloomfilter - ChaCha20-Poly1305 entschlüsseln den verschlüsselten Datenrahmen mit dem erhaltenen
tunnelNonceundinAEADKey - ChaCha20 entschlüsseln den verschlüsselten Datenrahmen mit dem erhaltenen
tunnelNonce& demlayerKeydes Hops - ChaCha20 entschlüsseln den
obfsNoncemit demnonceKeydes Hops und dem erhaltenentunnelNonce, um den vorherigenobfsNoncezu erhalten - ChaCha20 entschlüsseln den erhaltenen
tunnelNoncemit demnonceKeydes Hops und dem entschlüsseltenobfsNonce, um den vorherigentunnelNoncezu erhalten - ChaCha20 entschlüsseln die verschlüsselten Daten mit dem entschlüsselten
tunnelNonce& demlayerKeydes vorherigen Hops - Wiederholen Sie die Schritte zur Nonce- und Schichtentschlüsselung für jeden Hop im Tunnel zurück zum IBGW
- Die AEAD-Frame-Entschlüsselung wird nur im ersten Durchlauf benötigt
// Für die erste Runde, ChaCha20-Poly1305 entschlüsseln die verschlüsselten Datenrahmen + MAC jeder Nachricht
// unter Verwendung des erhaltenen tunnelNonce und inAEADKey
msg = encTunMsg \|\| MAC
tunnelNonce = received tunnelNonce
encTunMsg = ChaCha20-Poly1305-Decrypt(msg, nonce = tunnelNonce, key = inAEADKey)
// Wiederholen für jeden Hop im Tunnel zurück zum IBGW
// Für jede Runde, ChaCha20 entschlüsseln jede Hop-Schichtverschlüsselung auf jedem Datenrahmen der Nachricht
// Ersetzen Sie den erhaltenen tunnelNonce durch den im vorherigen Durchlauf entschlüsselten tunnelNonce für jeden Hop
decMsg = ChaCha20(msg = encTunMsg, nonce = tunnelNonce, key = layerKey)
obfsNonce = ChaCha20(msg = obfsNonce, nonce = tunnelNonce, key = nonceKey)
tunnelNonce = ChaCha20(msg = tunnelNonce, nonce = obfsNonce, key = nonceKey)
Sicherheitsanalyse für ChaCha20+ChaCha20-Poly1305 Tunnel-Schicht-Verschlüsselung
Der Wechsel von AES256/ECB+AES256/CBC zu ChaCha20+ChaCha20-Poly1305 bietet eine Reihe von Vorteilen und neue Sicherheitsüberlegungen.
Die größten Sicherheitsüberlegungen, die berücksichtigt werden müssen, sind, dass ChaCha20- und ChaCha20-Poly1305-Nonces für die Lebensdauer des verwendeten Schlüssels pro Nachricht einzigartig sein müssen.
Das Versäumnis, einzigartige Nonces mit demselben Schlüssel für verschiedene Nachrichten zu verwenden, führt zu einem Ausfall von ChaCha20 und ChaCha20-Poly1305.
Ein angehängter obfsNonce ermöglicht es dem IBEP, den tunnelNonce für die Schichtverschlüsselung jedes Hops zu entschlüsseln und den vorherigen Nonce wiederherzustellen.
Der obfsNonce zusammen mit dem tunnelNonce enthüllt keine neuen Informationen an die Tunnel-Hops,
da der obfsNonce mit dem verschlüsselten tunnelNonce verschlüsselt wird. Dies ermöglicht es dem IBEP auch, den vorherigen obfsNonce auf ähnliche Weise wie die Wiederherstellung des tunnelNonce wiederherzustellen.
Der größte Sicherheitsvorteil besteht darin, dass es keine Bestätigungs- oder Orangenangriffe gegen ChaCha20 gibt, und die Verwendung von ChaCha20-Poly1305 zwischen den Hops bietet AEAD-Schutz gegen die Manipulation der Verschlüsselung durch Außerhalb der BandmitM-Angreifer.
Es gibt praktische Orangenangriffe gegen AES256/ECB + AES256/CBC, wenn der Schlüssel erneut verwendet wird (wie in der Tunnel-Schicht-Verschlüsselung).
Die Orangenangriffe gegen AES256/ECB funktionieren nicht, aufgrund der doppelten Verschlüsselung und der Verschlüsselung über einen einzelnen Block (den Tunnel-IV).
Die Padding-Oracle-Angriffe gegen AES256/CBC funktionieren nicht, da kein Padding verwendet wird. Wenn sich die Tunnel-Nachrichtslänge jemals auf Nicht-mod-16-Längen änderte, wäre AES256/CBC aufgrund abgelehnter doppelter IVs immer noch nicht anfällig.
Beide Angriffe werden auch durch das Verbot mehrerer Oracle-Anfragen mit derselben IV blockiert, da doppelte IVs abgelehnt werden.