NTCP 2

Proposal 111
Fermé
Author EinMByte, orignal, psi, str4d, zzz
Created 2014-02-13
Last Updated 2019-08-13
Target Version 0.9.36
Implemented In 0.9.36
Supercedes: 106

Remarque

La phase de proposition est fermée. Voir SPEC pour la spécification officielle. Cette proposition peut encore être référencée pour des informations contextuelles.

Aperçu

Cette proposition décrit un protocole d’accord de clés authentifié pour améliorer la résistance de NTCP à diverses formes d’identification automatisée et d’attaques.

La proposition est organisée comme suit : les objectifs de sécurité sont présentés, suivis d’une discussion du protocole de base. Ensuite, une spécification complète de tous les messages du protocole est fournie. Enfin, les adresses des routeurs et l’identification de version sont discutées. Une annexe traitant d’une attaque générique sur les schémas de padding courants est également incluse, ainsi qu’une annexe contenant un certain nombre de candidats pour le chiffrement authentifié.

Comme pour les autres transports I2P, NTCP2 est défini uniquement pour le transport point-à-point (router-à-router) des messages I2NP. Ce n’est pas un canal de données à usage général.

Motivation

Les données NTCP sont chiffrées après le premier message (et le premier message semble être des données aléatoires), empêchant ainsi l’identification du protocole par « analyse de charge utile ». Il reste toutefois vulnérable à l’identification du protocole par « analyse de flux ». C’est parce que les 4 premiers messages (c’est-à-dire la négociation) ont une longueur fixe (288, 304, 448, et 48 octets).

En ajoutant des quantités aléatoires de données aléatoires à chacun des messages, nous pouvons rendre cela beaucoup plus difficile.

Les auteurs reconnaissent que les pratiques de sécurité standard suggéreraient d’utiliser un protocole existant tel que TLS, mais il s’agit de Prop104 et cela a ses propres problèmes. Le cas échéant, des paragraphes “travaux futurs” ont été ajoutés pour indiquer les fonctionnalités manquantes ou les sujets de discussion.

Objectifs de conception

  • Prendre en charge NTCP 1 et 2 sur un seul port, détection automatique, et publié comme un seul “transport” (c’est-à-dire RouterAddress) dans la NetDB.

  • Publier le support pour la version 1 uniquement, la version 2 uniquement, ou 1+2 dans la NetDB dans un champ séparé, et définir par défaut la version 1 uniquement (ne pas lier le support de version à une version de router particulière)

  • S’assurer que toutes les implémentations (Java/i2pd/Kovri/go) peuvent ajouter le support de la version 2 (ou non) selon leurs propres calendriers

  • Ajouter un remplissage aléatoire à tous les messages NTCP incluant les messages de handshake et de données (c’est-à-dire l’obfuscation de longueur afin que tous les messages ne soient pas un multiple de 16 octets) Fournir un mécanisme d’options pour que les deux côtés puissent demander un remplissage minimum et maximum et/ou une distribution de remplissage. Les spécificités de la distribution de remplissage dépendent de l’implémentation et peuvent ou non être spécifiées dans le protocole lui-même.

  • Masquer le contenu des messages qui ne sont pas chiffrés (1 et 2), suffisamment pour que les boîtiers DPI et les signatures AV ne puissent pas facilement les classifier. S’assurer également que les messages envoyés à un seul pair ou ensemble de pairs n’aient pas un motif de bits similaire.

  • Corriger la perte de bits dans DH due au format Java Ticket1112, possiblement (probablement ?) en passant à X25519.

  • Passer à une vraie fonction de dérivation de clé (KDF) plutôt que d’utiliser le résultat DH tel quel ?

  • Ajouter la “résistance au sondage” (comme l’appelle Tor) ; cela inclut la résistance aux attaques par rejeu.

  • Maintenir un échange de clés authentifié bidirectionnel (2W-AKE). 1W-AKE n’est pas suffisant pour notre application.

  • Continuer à utiliser les signatures de type variable et de longueur variable (provenant de la clé de signature RouterIdentity publiée) comme partie de l’authentification. S’appuyer sur une clé publique statique publiée dans le RouterInfo comme autre partie de l’authentification.

  • Ajouter options/version dans le handshake pour l’extensibilité future.

  • Ajouter une résistance à la segmentation TCP malveillante de type MitM si possible.

  • N’augmente pas significativement les ressources CPU requises pour l’établissement de connexion ; si possible, les réduire significativement.

  • Ajouter l’authentification de message (MAC), possiblement HMAC-SHA256 et Poly1305, et supprimer la somme de contrôle Adler.

  • Raccourcir et simplifier l’en-tête I2NP : Raccourcir l’expiration à 4 octets, comme dans SSU. Supprimer la somme de contrôle SHA256 tronquée d’un octet.

  • Si possible, réduire la négociation à 4 messages et deux allers-retours vers une négociation à 3 messages et un aller-retour, comme dans SSU. Cela nécessiterait de déplacer la signature de Bob du message 4 vers le message 2. Rechercher la raison des 4 messages dans les archives d’emails/status/réunions vieilles de dix ans.

  • Minimiser la surcharge protocolaire avant le bourrage. Bien que du bourrage soit ajouté, et possiblement en grande quantité, la surcharge avant le bourrage reste de la surcharge. Les nœuds à faible bande passante doivent pouvoir utiliser NTCP2.

  • Maintenir les horodatages pour la détection de rejeu et de décalage.

  • Éviter tout problème lié à l’année 2038 dans les horodatages, doit fonctionner au moins jusqu’en 2106.

  • Augmenter la taille maximale des messages de 16K à 32K ou 64K.

  • Toute nouvelle primitive cryptographique devrait être facilement disponible dans les bibliothèques pour une utilisation dans les implémentations de router Java (1.7), C++, et Go.

  • Inclure des représentants des développeurs de routeurs Java, C++ et Go dans la conception.

  • Minimiser les changements (mais il y en aura encore beaucoup).

  • Prendre en charge les deux versions dans un ensemble de code commun (ceci peut ne pas être possible et dépend de l’implémentation dans tous les cas).

Non-Goals

  • Résistance DPI à toute épreuve… ce seraient les transports enfichables, Prop109.

  • Un transport basé sur TLS (ou ressemblant à HTTPS)… qui serait Prop104.

  • Il est acceptable de changer la cryptographie de flux symétrique.

  • Résistance DPI basée sur le timing (le timing/délais entre messages peuvent être dépendants de l’implémentation ; les délais intra-message peuvent être introduits à tout moment, y compris avant l’envoi du padding aléatoire, par exemple). Les délais artificiels (ce qu’obfs4 appelle IAT ou inter-arrival time) sont indépendants du protocole lui-même.

  • Déniabilité de participation à une session (il y a des signatures dedans).

Objectifs non poursuivis qui peuvent être partiellement reconsidérés ou discutés :

  • Le degré de protection contre l’inspection approfondie des paquets (DPI)

  • Sécurité post-quantique (PQ)

  • Déniabilité

  • Implémenter une configuration de test NTCP 1/2

Security Goals

Nous considérons trois parties :

  • Alice, qui souhaite établir une nouvelle session.
  • Bob, avec qui Alice souhaite établir une session.
  • Mallory, l’« homme du milieu » entre Alice et Bob.

Au maximum deux participants peuvent mener des attaques actives.

Alice et Bob possèdent tous deux une paire de clés statique, qui est contenue dans leur RouterIdentity.

Le protocole proposé tente de permettre à Alice et Bob de convenir d’une clé secrète partagée (K) selon les exigences suivantes :

  1. Sécurité de la clé privée : ni Bob ni Mallory n’apprennent quoi que ce soit sur la clé privée statique d’Alice. Symétriquement, Alice n’apprend rien sur la clé privée statique de Bob.

  2. La clé de session K n’est connue que par Alice et Bob.

  3. Confidentialité persistante parfaite : la clé de session convenue reste secrète dans le futur, même lorsque les clés privées statiques d’Alice et/ou de Bob sont révélées après que la clé ait été établie.

  4. Authentification bidirectionnelle : Alice est certaine qu’elle a établi une session avec Bob, et vice versa.

  5. Protection contre le DPI en ligne : S’assurer qu’il n’est pas trivial de détecter qu’Alice et Bob sont engagés dans le protocole en utilisant uniquement des techniques d’inspection approfondie des paquets (DPI) simples. Voir ci-dessous.

  6. Déni limité : ni Alice ni Bob ne peuvent nier leur participation au protocole, mais si l’un d’eux divulgue la clé partagée, l’autre partie peut nier l’authenticité du contenu des données transmises.

La présente proposition tente de fournir les cinq exigences basées sur le protocole Station-To-Station (STS). Notez que ce protocole est également la base du protocole SSU.

Additional DPI Discussion

Nous supposons deux composants DPI :

1) Online DPI

DPI en ligne inspectant tous les flux en temps réel. Les connexions peuvent être bloquées ou autrement altérées. Les données de connexion ou métadonnées peuvent être identifiées et stockées pour une analyse hors ligne. Le DPI en ligne n’a pas accès à la base de données réseau I2P. Le DPI en ligne n’a qu’une capacité de calcul temps réel limitée, incluant le calcul de longueur, l’inspection de champs, et des calculs simples tels que XOR. Le DPI en ligne a la capacité d’effectuer des fonctions cryptographiques temps réel rapides telles qu’AES, AEAD, et hachage, mais celles-ci seraient trop coûteuses à appliquer à la plupart ou à tous les flux. Toute application de ces opérations cryptographiques ne s’appliquerait qu’aux flux sur des combinaisons IP/Port préalablement identifiées par analyse hors ligne. Le DPI en ligne n’a pas la capacité d’effectuer des fonctions cryptographiques à haute charge telles que DH ou elligator2. Le DPI en ligne n’est pas conçu spécifiquement pour détecter I2P, bien qu’il puisse avoir des règles de classification limitées à cette fin.

L’objectif est d’empêcher l’identification du protocole par un DPI en ligne.

La notion de DPI en ligne ou « directe » inclut ici les capacités adversariales suivantes :

  1. La capacité d’inspecter toutes les données envoyées ou reçues par la cible.

  2. La capacité d’effectuer des opérations sur les données observées, comme l’application de chiffrements par blocs ou de fonctions de hachage.

  3. La capacité de stocker et de comparer avec les messages précédemment envoyés.

  4. La capacité de modifier, retarder ou fragmenter les paquets.

Cependant, le DPI en ligne est supposé avoir les restrictions suivantes :

  1. L’impossibilité de mapper les adresses IP aux hachages de router. Bien que cela soit trivial avec un accès en temps réel à la base de données réseau, cela nécessiterait un système DPI spécifiquement conçu pour cibler I2P.

  2. L’incapacité d’utiliser les informations de temporisation pour détecter le protocole.

  3. De manière générale, la boîte à outils DPI en ligne ne contient aucun outil intégré spécifiquement conçu pour la détection I2P. Cela inclut la création de “honeypots”, qui incluraient par exemple un remplissage non aléatoire dans leurs messages. Notez que cela n’exclut pas les systèmes d’apprentissage automatique ou les outils DPI hautement configurables tant qu’ils répondent aux autres exigences.

Pour contrer l’analyse de charge utile, il est assuré que tous les messages sont indiscernables de données aléatoires. Cela nécessite également que leur longueur soit aléatoire, ce qui est plus compliqué que de simplement ajouter un remplissage aléatoire. En fait, dans l’Annexe A, les auteurs soutiennent qu’un schéma de remplissage naïf (c’est-à-dire uniforme) ne résout pas le problème. L’Annexe A propose donc d’inclure soit des délais aléatoires, soit de développer un schéma de remplissage alternatif qui peut fournir une protection raisonnable contre l’attaque proposée.

Pour se protéger contre la sixième entrée ci-dessus, les implémentations devraient inclure des délais aléatoires dans le protocole. De telles techniques ne sont pas couvertes par cette proposition, mais elles pourraient également résoudre les problèmes de longueur de bourrage. En résumé, la proposition fournit une bonne protection contre l’analyse de charge utile (lorsque les considérations de l’Annexe A sont prises en compte), mais seulement une protection limitée contre l’analyse de flux.

2) Offline DPI

DPI hors ligne inspectant les données stockées par le DPI en ligne pour une analyse ultérieure. Le DPI hors ligne peut être spécifiquement conçu pour détecter I2P. Le DPI hors ligne n’a pas d’accès en temps réel à la base de données réseau I2P. Le DPI hors ligne a accès à cette spécification et à d’autres spécifications I2P. Le DPI hors ligne dispose de capacités de calcul illimitées, incluant toutes les fonctions cryptographiques définies dans cette spécification.

Le DPI hors ligne n’a pas la capacité de bloquer les connexions existantes. Le DPI hors ligne a la capacité d’effectuer en temps quasi-réel (dans les minutes suivant la configuration) l’envoi vers l’hôte/port des parties, par exemple TCP RST. Le DPI hors ligne a la capacité d’effectuer en temps quasi-réel (dans les minutes suivant la configuration) la relecture de messages précédents (modifiés ou non) pour du “sondage” ou d’autres raisons.

Ce n’est pas un objectif d’empêcher l’identification du protocole par un DPI hors ligne. Tout décodage de données obscurcies dans les deux premiers messages, qui est implémenté par les routers I2P, peut également être implémenté par le DPI hors ligne.

L’objectif est de rejeter les tentatives de connexion utilisant la rediffusion de messages précédents.

Future work

  • Considérez le comportement du protocole lorsque les paquets sont supprimés ou réordonnés par un attaquant. Des travaux récents intéressants dans ce domaine peuvent être trouvés dans IACR-1150.

  • Fournir une classification plus précise des systèmes DPI, en tenant compte de la littérature existante liée au sujet.

  • Discuter de la sécurité formelle du protocole proposé, idéalement en prenant en compte le modèle d’attaquant DPI.

Noise Protocol Framework

Cette proposition fournit les exigences basées sur le Noise Protocol Framework NOISE (Révision 33, 2017-10-04). Noise a des propriétés similaires au protocole Station-To-Station, qui est la base du protocole SSU. Dans la terminologie Noise, Alice est l’initiateur, et Bob est le répondeur.

NTCP2 est basé sur le protocole Noise Noise_XK_25519_ChaChaPoly_SHA256. (L’identifiant réel pour la fonction de dérivation de clé initiale est “Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256” pour indiquer les extensions I2P - voir la section KDF 1 ci-dessous) Ce protocole Noise utilise les primitives suivantes :

  • Handshake Pattern: XK Alice transmet sa clé à Bob (X) Alice connaît déjà la clé statique de Bob (K)

  • Fonction DH : X25519 X25519 DH avec une longueur de clé de 32 octets comme spécifié dans RFC-7748.

  • Fonction de chiffrement : ChaChaPoly AEAD_CHACHA20_POLY1305 tel que spécifié dans la RFC-7539 section 2.8. Nonce de 12 octets, avec les 4 premiers octets définis à zéro.

  • Fonction de hachage : SHA256 Hachage standard de 32 octets, déjà utilisé de manière extensive dans I2P.

Objectifs de sécurité

Cette proposition définit les améliorations suivantes à Noise_XK_25519_ChaChaPoly_SHA256. Celles-ci suivent généralement les directives de la section 13 de NOISE.

  1. Les clés éphémères en clair sont obfusquées avec un chiffrement AES utilisant une clé et un IV connus. Ceci est plus rapide qu’elligator2.

  2. Un rembourrage aléatoire en texte clair est ajouté aux messages 1 et 2. Le rembourrage en texte clair est inclus dans le calcul du hachage de négociation (MixHash). Voir les sections KDF ci-dessous pour le message 2 et la partie 1 du message 3. Un rembourrage AEAD aléatoire est ajouté au message 3 et aux messages de la phase de données.

  3. Un champ de longueur de trame de deux octets est ajouté, comme requis pour Noise sur TCP, et comme dans obfs4. Ceci est utilisé uniquement dans les messages de la phase de données. Les trames AEAD des messages 1 et 2 ont une longueur fixe. La trame AEAD de la partie 1 du message 3 a une longueur fixe. La longueur de la trame AEAD de la partie 2 du message 3 est spécifiée dans le message 1.

  4. Le champ de longueur de trame de deux octets est obscurci avec SipHash-2-4, comme dans obfs4.

  5. Le format de payload est défini pour les messages 1,2,3, et la phase de données. Bien sûr, ceci n’est pas défini dans Noise.

New Cryptographic Primitives for I2P

Les implémentations de router I2P existantes nécessiteront des implémentations pour les primitives cryptographiques standard suivantes, qui ne sont pas requises pour les protocoles I2P actuels :

  1. Génération de clé X25519 et DH

  2. AEAD_ChaCha20_Poly1305 (abrégé en ChaChaPoly ci-dessous)

  3. SipHash-2-4

Processing overhead estimate

Tailles des messages pour les 3 messages :

  1. 64 octets + rembourrage (NTCP était 288 octets) 2) 64 octets + rembourrage (NTCP était 304 octets) 3) environ 64 octets + informations routeur Alice + rembourrage Les informations routeur moyennes font environ 750 octets Total moyen 814 octets avant rembourrage (NTCP était 448 octets) 4) non requis dans NTCP2 (NTCP était 48 octets)

Total avant remplissage : NTCP2 : 942 octets NTCP : 1088 octets Notez que si Alice se connectait à Bob dans le but d’envoyer un message DatabaseStore de son RouterInfo, ce message n’est pas requis, économisant environ 800 octets.

Les opérations cryptographiques suivantes sont requises par chaque partie pour compléter la négociation et commencer la phase de données :

  • AES : 2
  • SHA256 : 7 (Alice), 6 (Bob) (sans inclure 1 Alice, 2 Bob précalculés pour toutes les connexions) (sans inclure HMAC-SHA256)
  • HMAC-SHA256 : 19
  • ChaChaPoly : 4
  • Génération de clé X25519 : 1
  • X25519 DH : 3
  • Vérification de signature : 1 (Bob) (Alice a précédemment signé lors de la génération de son RI) Vraisemblablement Ed25519 (dépendant du type de signature RI)

Les opérations cryptographiques suivantes sont requises par chaque partie pour chaque message de phase de données :

  • SipHash : 1
  • ChaChaPoly : 1

Messages

Tous les messages NTCP2 font 65537 octets ou moins en longueur. Le format de message est basé sur les messages Noise, avec des modifications pour le tramage et l’indiscernabilité. Les implémentations utilisant des bibliothèques Noise standard peuvent avoir besoin de pré-traiter les messages reçus vers/depuis le format de message Noise. Tous les champs chiffrés sont des textes chiffrés AEAD.

La séquence d’établissement est la suivante :

Alice                           Bob

  SessionRequest ------------------->
  <------------------- SessionCreated
  SessionConfirmed ----------------->

En utilisant la terminologie Noise, la séquence d’établissement et de données est la suivante : (Propriétés de sécurité de la charge utile)

XK(s, rs):           Authentication   Confidentiality
    <- s
    ...
    -> e, es                  0                2
    <- e, ee                  2                1
    -> s, se                  2                5
    <-                        2                5

Une fois qu’une session a été établie, Alice et Bob peuvent échanger des messages Data.

Tous les types de messages (SessionRequest, SessionCreated, SessionConfirmed, Data et TimeSync) sont spécifiés dans cette section.

Quelques notations :

  • RH_A = Hachage de routeur pour Alice (32 octets)
  • RH_B = Hachage de routeur pour Bob (32 octets)

Authenticated Encryption

Il y a trois instances distinctes de chiffrement authentifié (CipherStates). Une pendant la phase de négociation (handshake), et deux (transmission et réception) pour la phase de données. Chacune a sa propre clé provenant d’une KDF.

Les données chiffrées/authentifiées seront représentées comme

+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   Encrypted and authenticated data    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

Objectifs non visés

Format de données chiffré et authentifié.

Entrées des fonctions de chiffrement/déchiffrement :

k :: 32 byte cipher key, as generated from KDF

  nonce :: Counter-based nonce, 12 bytes.
           Starts at 0 and incremented for each message.
           First four bytes are always zero.
           Last eight bytes are the counter, little-endian encoded.
           Maximum value is 2**64 - 2.
           Connection must be dropped and restarted after
           it reaches that value.
           The value 2**64 - 1 must never be sent.

  ad :: In handshake phase:
        Associated data, 32 bytes.
        The SHA256 hash of all preceding data.
        In data phase:
        Zero bytes

  data :: Plaintext data, 0 or more bytes

Sortie de la fonction de chiffrement, entrée de la fonction de déchiffrement :

+----+----+----+----+----+----+----+----+
  |Obfs Len |                             |
  +----+----+                             +
  |       ChaCha20 encrypted data         |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Poly1305 Message Authentication Code |
  +              (MAC)                    +
  |             16 bytes                  |
  +----+----+----+----+----+----+----+----+

  Obfs Len :: Length of (encrypted data + MAC) to follow, 16 - 65535
              Obfuscation using SipHash (see below)
              Not used in message 1 or 2, or message 3 part 1, where the length is fixed
              Not used in message 3 part 1, as the length is specified in message 1

  encrypted data :: Same size as plaintext data, 0 - 65519 bytes

  MAC :: Poly1305 message authentication code, 16 bytes

Pour ChaCha20, ce qui est décrit ici correspond à RFC-7539, qui est également utilisé de manière similaire dans TLS RFC-7905.

Notes

  • Étant donné que ChaCha20 est un chiffrement de flux, les textes en clair n’ont pas besoin d’être complétés par du bourrage. Les octets supplémentaires du flux de clés sont supprimés.

  • La clé pour le chiffrement (256 bits) est convenue au moyen du KDF SHA256. Les détails du KDF pour chaque message sont dans des sections séparées ci-dessous.

  • Les trames ChaChaPoly pour les messages 1, 2, et la première partie du message 3, sont de taille connue. À partir de la seconde partie du message 3, les trames sont de taille variable. La taille de la partie 1 du message 3 est spécifiée dans le message 1. À partir de la phase de données, les trames sont préfixées avec une longueur de deux octets obfusquée avec SipHash comme dans obfs4.

  • Le padding est en dehors de la trame de données authentifiées pour les messages 1 et 2. Le padding est utilisé dans la KDF pour le message suivant, donc toute altération sera détectée. À partir du message 3, le padding est à l’intérieur de la trame de données authentifiées.

Objectifs connexes

  • Dans les messages 1, 2, et les parties 1 et 2 du message 3, la taille du message AEAD est connue à l’avance. En cas d’échec de l’authentification AEAD, le destinataire doit arrêter le traitement ultérieur des messages et fermer la connexion sans répondre. Ceci devrait être une fermeture anormale (TCP RST).

  • Pour la résistance au sondage, dans le message 1, après un échec AEAD, Bob devrait définir un délai d’attente aléatoire (plage à déterminer) puis lire un nombre aléatoire d’octets (plage à déterminer) avant de fermer la socket. Bob devrait maintenir une liste noire des IP avec des échecs répétés.

  • Dans la phase de données, la taille du message AEAD est “chiffrée” (obfusquée) avec SipHash. Il faut prendre soin d’éviter de créer un oracle de déchiffrement. En cas d’échec d’authentification AEAD de la phase de données, le destinataire devrait définir un délai d’attente aléatoire (plage à déterminer) puis lire un nombre aléatoire d’octets (plage à déterminer). Après la lecture, ou en cas de délai d’attente de lecture dépassé, le destinataire devrait envoyer une charge utile avec un bloc de terminaison contenant un code de raison “échec AEAD”, et fermer la connexion.

  • Prendre la même action d’erreur pour une valeur de champ de longueur invalide dans la phase de données.

Key Derivation Function (KDF) (for handshake message 1)

Le KDF génère une clé de chiffrement de phase de handshake k à partir du résultat DH, en utilisant HMAC-SHA256(key, data) tel que défini dans RFC-2104. Il s’agit des fonctions InitializeSymmetric(), MixHash(), et MixKey(), exactement telles que définies dans la spécification Noise.

This is the "e" message pattern:

  // Define protocol_name.
  Set protocol_name = "Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256"
   (48 bytes, US-ASCII encoded, no NULL termination).

  // Define Hash h = 32 bytes
  h = SHA256(protocol_name);

  Define ck = 32 byte chaining key. Copy the h data to ck.
  Set ck = h

  Define rs = Bob's 32-byte static key as published in the RouterInfo

  // MixHash(null prologue)
  h = SHA256(h);

  // up until here, can all be precalculated by Alice for all outgoing connections

  // Alice must validate that Bob's static key is a valid point on the curve here.

  // Bob static key
  // MixHash(rs)
  // || below means append
  h = SHA256(h || rs);

  // up until here, can all be precalculated by Bob for all incoming connections

  This is the "e" message pattern:

  Alice generates her ephemeral DH key pair e.

  // Alice ephemeral key X
  // MixHash(e.pubkey)
  // || below means append
  h = SHA256(h || e.pubkey);

  // h is used as the associated data for the AEAD in message 1
  // Retain the Hash h for the message 2 KDF


  End of "e" message pattern.

  This is the "es" message pattern:

  // DH(e, rs) == DH(s, re)
  Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's static key
  Set input_key_material = X25519 DH result

  // MixKey(DH())

  Define temp_key = 32 bytes
  Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104)
  // Generate a temp key from the chaining key and DH result
  // ck is the chaining key, defined above
  temp_key = HMAC-SHA256(ck, input_key_material)
  // overwrite the DH result in memory, no longer needed
  input_key_material = (all zeros)

  // Output 1
  // Set a new chaining key from the temp key
  // byte() below means a single byte
  ck =       HMAC-SHA256(temp_key, byte(0x01)).

  // Output 2
  // Generate the cipher key k
  Define k = 32 bytes
  // || below means append
  // byte() below means a single byte
  k =        HMAC-SHA256(temp_key, ck || byte(0x02)).
  // overwrite the temp_key in memory, no longer needed
  temp_key = (all zeros)

  // retain the chaining key ck for message 2 KDF


  End of "es" message pattern.

Discussion supplémentaire sur la DPI

Alice envoie à Bob.

Contenu Noise : clé éphémère X d’Alice Charge utile Noise : bloc d’option de 16 octets Charge utile non-noise : Bourrage aléatoire

(Propriétés de Sécurité de la Charge Utile)

XK(s, rs):           Authentication   Confidentiality
    -> e, es                  0                2

    Authentication: None (0).
    This payload may have been sent by any party, including an active attacker.

    Confidentiality: 2.
    Encryption to a known recipient, forward secrecy for sender compromise
    only, vulnerable to replay.  This payload is encrypted based only on DHs
    involving the recipient's static key pair.  If the recipient's static
    private key is compromised, even at a later date, this payload can be
    decrypted.  This message can also be replayed, since there's no ephemeral
    contribution from the recipient.

    "e": Alice generates a new ephemeral key pair and stores it in the e
         variable, writes the ephemeral public key as cleartext into the
         message buffer, and hashes the public key along with the old h to
         derive a new h.

    "es": A DH is performed between the Alice's ephemeral key pair and the
          Bob's static key pair.  The result is hashed along with the old ck to
          derive a new ck and k, and n is set to zero.

La valeur X est chiffrée pour assurer l’indiscernabilité et l’unicité de la charge utile, qui sont des contre-mesures DPI nécessaires. Nous utilisons le chiffrement AES pour y parvenir, plutôt que des alternatives plus complexes et plus lentes telles qu’elligator2. Le chiffrement asymétrique vers la clé publique du router de Bob serait bien trop lent. Le chiffrement AES utilise le hash du router de Bob comme clé et l’IV de Bob tel que publié dans la base de données réseau.

Le chiffrement AES est uniquement pour la résistance DPI. Toute partie connaissant le hachage du router de Bob, et l’IV, qui sont publiés dans la base de données réseau, peut déchiffrer la valeur X dans ce message.

Le padding n’est pas chiffré par Alice. Il peut être nécessaire pour Bob de déchiffrer le padding, pour empêcher les attaques temporelles.

Contenu brut :

+----+----+----+----+----+----+----+----+
|                                       |
+        obfuscated with RH_B           +
|       AES-CBC-256 encrypted X         |
+             (32 bytes)                +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|   ChaChaPoly frame                    |
+             (32 bytes)                +
|   k defined in KDF for message 1      |
+   n = 0                               +
|   see KDF for associated data         |
+----+----+----+----+----+----+----+----+
|     unencrypted authenticated         |
~         padding (optional)            ~
|     length defined in options block   |
+----+----+----+----+----+----+----+----+

X :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian
        key: RH_B
        iv: As published in Bobs network database entry

padding :: Random data, 0 or more bytes.
           Total message length must be 65535 bytes or less.
           Total message length must be 287 bytes or less if
           Bob is publishing his address as NTCP
           (see Version Detection section below).
           Alice and Bob will use the padding data in the KDF for message 2.
           It is authenticated so that any tampering will cause the
           next message to fail.

Données non chiffrées (tag d’authentification Poly1305 non affiché) :

+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|                   X                   |
+              (32 bytes)               +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|               options                 |
+              (16 bytes)               +
|                                       |
+----+----+----+----+----+----+----+----+
|     unencrypted authenticated         |
+         padding (optional)            +
|     length defined in options block   |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

X :: 32 bytes, X25519 ephemeral key, little endian

options :: options block, 16 bytes, see below

padding :: Random data, 0 or more bytes.
           Total message length must be 65535 bytes or less.
           Total message length must be 287 bytes or less if
           Bob is publishing his address as "NTCP"
           (see Version Detection section below)
           Alice and Bob will use the padding data in the KDF for message 2.
           It is authenticated so that any tampering will cause the
           next message to fail.

Bloc d’options : Remarque : Tous les champs sont en big-endian.

+----+----+----+----+----+----+----+----+
| id | ver|  padLen | m3p2len | Rsvd(0) |
+----+----+----+----+----+----+----+----+
|        tsA        |   Reserved (0)    |
+----+----+----+----+----+----+----+----+

id :: 1 byte, the network ID (currently 2, except for test networks)
      As of 0.9.42. See proposal 147.

ver :: 1 byte, protocol version (currently 2)

padLen :: 2 bytes, length of the padding, 0 or more
          Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
          (Distribution to be determined, see Appendix A.)

m3p2Len :: 2 bytes, length of the the second AEAD frame in SessionConfirmed
           (message 3 part 2) See notes below

Rsvd :: 2 bytes, set to 0 for compatibility with future options

tsA :: 4 bytes, Unix timestamp, unsigned seconds.
       Wraps around in 2106

Reserved :: 4 bytes, set to 0 for compatibility with future options

Notes

  • Lorsque l’adresse publiée est “NTCP”, Bob supporte à la fois NTCP et NTCP2 sur le même port. Pour des raisons de compatibilité, lors de l’initiation d’une connexion vers une adresse publiée comme “NTCP”, Alice doit limiter la taille maximale de ce message, padding inclus, à 287 octets ou moins. Ceci facilite l’identification automatique du protocole par Bob. Lorsque publiée comme “NTCP2”, il n’y a aucune restriction de taille. Voir les sections Adresses Publiées et Détection de Version ci-dessous.

  • La valeur X unique dans le bloc AES initial garantit que le texte chiffré est différent pour chaque session.

  • Bob doit rejeter les connexions où la valeur du timestamp est trop éloignée de l’heure actuelle. Appelons le delta de temps maximum “D”. Bob doit maintenir un cache local des valeurs de handshake précédemment utilisées et rejeter les doublons, pour éviter les attaques par rejeu. Les valeurs dans le cache doivent avoir une durée de vie d’au moins 2*D. Les valeurs du cache dépendent de l’implémentation, cependant la valeur X de 32 octets (ou son équivalent chiffré) peut être utilisée.

  • Les clés éphémères Diffie-Hellman ne doivent jamais être réutilisées, pour prévenir les attaques cryptographiques, et la réutilisation sera rejetée comme une attaque par rejeu.

  • Les options “KE” et “auth” doivent être compatibles, c’est-à-dire que le secret partagé K doit avoir la taille appropriée. Si davantage d’options “auth” sont ajoutées, cela pourrait implicitement changer la signification du flag “KE” pour utiliser un KDF différent ou une taille de troncature différente.

  • Bob doit valider que la clé éphémère d’Alice est un point valide sur la courbe ici.

  • Le padding devrait être limité à une quantité raisonnable. Bob peut rejeter les connexions avec un padding excessif. Bob spécifiera ses options de padding dans le message 2. Directives min/max à déterminer. Taille aléatoire de 0 à 31 octets minimum ? (Distribution à déterminer, voir Annexe A.)

  • En cas d’erreur, y compris AEAD, DH, horodatage, rejeu apparent, ou échec de validation de clé, Bob doit arrêter tout traitement de message supplémentaire et fermer la connexion sans répondre. Ceci devrait être une fermeture anormale (TCP RST). Pour la résistance au sondage, après un échec AEAD, Bob devrait définir un délai d’attente aléatoire (plage à déterminer) puis lire un nombre aléatoire d’octets (plage à déterminer), avant de fermer la socket.

  • Atténuation DoS : DH est une opération relativement coûteuse. Comme avec le protocole NTCP précédent, les routeurs doivent prendre toutes les mesures nécessaires pour éviter l’épuisement du CPU ou des connexions. Placer des limites sur le nombre maximum de connexions actives et le nombre maximum d’établissements de connexions en cours. Appliquer des délais d’attente de lecture (à la fois par lecture et total pour “slowloris”). Limiter les connexions répétées ou simultanées provenant de la même source. Maintenir des listes noires pour les sources qui échouent de façon répétée. Ne pas répondre à l’échec AEAD.

  • Pour faciliter la détection rapide de version et l’établissement de liaison, les implémentations doivent s’assurer qu’Alice met en mémoire tampon puis vide entièrement le contenu du premier message d’un coup, y compris le rembourrage. Cela augmente la probabilité que les données soient contenues dans un seul paquet TCP (sauf si segmenté par l’OS ou les middleboxes), et reçues d’un coup par Bob. De plus, les implémentations doivent s’assurer que Bob met en mémoire tampon puis vide entièrement le contenu du second message d’un coup, y compris le rembourrage, et que Bob met en mémoire tampon puis vide entièrement le contenu du troisième message d’un coup. Ceci est également pour l’efficacité et pour garantir l’efficacité du rembourrage aléatoire.

  • Champ “ver” : Le protocole Noise global, les extensions et le protocole NTCP incluant les spécifications de charge utile, indiquant NTCP2. Ce champ peut être utilisé pour indiquer le support de futurs changements.

  • Longueur de la partie 2 du message 3 : Il s’agit de la taille de la seconde trame AEAD (incluant le MAC de 16 octets) contenant les informations de routeur d’Alice et un remplissage optionnel qui sera envoyé dans le message SessionConfirmed. Comme les routeurs régénèrent et republient périodiquement leurs informations de routeur, la taille des informations de routeur actuelles peut changer avant l’envoi du message 3. Les implémentations doivent choisir l’une des deux stratégies suivantes : a) sauvegarder les informations de routeur actuelles à envoyer dans le message 3, afin que la taille soit connue, et optionnellement ajouter de la place pour le remplissage ; b) augmenter suffisamment la taille spécifiée pour permettre une éventuelle augmentation de la taille des informations de routeur, et toujours ajouter du remplissage lors de l’envoi effectif du message 3. Dans les deux cas, la longueur “m3p2len” incluse dans le message 1 doit correspondre exactement à la taille de cette trame lors de l’envoi dans le message 3.

  • Bob doit faire échouer la connexion si des données entrantes subsistent après avoir validé le message 1 et lu le padding. Il ne devrait y avoir aucune donnée supplémentaire d’Alice, car Bob n’a pas encore répondu avec le message 2.

  • Le champ network ID est utilisé pour identifier rapidement les connexions inter-réseaux. Si ce champ est non nul et ne correspond pas au network ID de Bob, Bob devrait se déconnecter et bloquer les futures connexions. Depuis la version 0.9.42. Voir la proposition 147 pour plus d’informations.

Key Derivation Function (KDF) (for handshake message 2 and message 3 part 1)


// take h saved from message 1 KDF
// MixHash(ciphertext)
h = SHA256(h || 32 byte encrypted payload from message 1)

// MixHash(padding)
// Only if padding length is nonzero
h = SHA256(h || random padding from message 1)

This is the "e" message pattern:

Bob generates his ephemeral DH key pair e.

// h is from KDF for handshake message 1
// Bob ephemeral key Y
// MixHash(e.pubkey)
// || below means append
h = SHA256(h || e.pubkey);

// h is used as the associated data for the AEAD in message 2
// Retain the Hash h for the message 3 KDF

End of "e" message pattern.

This is the "ee" message pattern:

// DH(e, re)
Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Alice's ephemeral key in memory, no longer needed
// Alice:
e(public and private) = (all zeros)
// Bob:
re = (all zeros)

// MixKey(DH())

Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)

// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck =       HMAC-SHA256(temp_key, byte(0x01)).

// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k =        HMAC-SHA256(temp_key, ck || byte(0x02)).
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)

// retain the chaining key ck for message 3 KDF

End of "ee" message pattern.

2) SessionCreated

Bob envoie à Alice.

Contenu Noise : clé éphémère Y de Bob Charge utile Noise : bloc d’option de 16 octets Charge utile non-noise : remplissage aléatoire

(Propriétés de Sécurité de la Charge Utile)

XK(s, rs):           Authentication   Confidentiality
  <- e, ee                  2                1

  Authentication: 2.
  Sender authentication resistant to key-compromise impersonation (KCI).
  The sender authentication is based on an ephemeral-static DH ("es" or "se")
  between the sender's static key pair and the recipient's ephemeral key pair.
  Assuming the corresponding private keys are secure, this authentication cannot be forged.

  Confidentiality: 1.
  Encryption to an ephemeral recipient.
  This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
  However, the sender has not authenticated the recipient,
  so this payload might be sent to any party, including an active attacker.


  "e": Bob generates a new ephemeral key pair and stores it in the e variable,
  writes the ephemeral public key as cleartext into the message buffer,
  and hashes the public key along with the old h to derive a new h.

  "ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
  The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

La valeur Y est chiffrée pour garantir l’indiscernabilité et l’unicité de la charge utile, qui sont des contre-mesures DPI nécessaires. Nous utilisons le chiffrement AES pour y parvenir, plutôt que des alternatives plus complexes et plus lentes telles qu’elligator2. Le chiffrement asymétrique avec la clé publique du router d’Alice serait bien trop lent. Le chiffrement AES utilise le hachage du router de Bob comme clé et l’état AES du message 1 (qui a été initialisé avec l’IV de Bob tel que publié dans la base de données réseau).

Le chiffrement AES est uniquement pour la résistance à la DPI. Toute partie connaissant le hash du router de Bob et l’IV, qui sont publiés dans la base de données réseau, et ayant capturé les 32 premiers octets du message 1, peut déchiffrer la valeur Y dans ce message.

Contenu brut :

+----+----+----+----+----+----+----+----+
|                                       |
+        obfuscated with RH_B           +
|       AES-CBC-256 encrypted Y         |
+              (32 bytes)               +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|   ChaChaPoly frame                    |
+   Encrypted and authenticated data    +
|   32 bytes                            |
+   k defined in KDF for message 2      +
|   n = 0; see KDF for associated data  |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|     unencrypted authenticated         |
+         padding (optional)            +
|     length defined in options block   |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

Y :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian
        key: RH_B
        iv: Using AES state from message 1

Données non chiffrées (tag d’authentification Poly1305 non affiché) :

+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|                  Y                    |
+              (32 bytes)               +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|               options                 |
+              (16 bytes)               +
|                                       |
+----+----+----+----+----+----+----+----+
|     unencrypted authenticated         |
+         padding (optional)            +
|     length defined in options block   |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

Y :: 32 bytes, X25519 ephemeral key, little endian

options :: options block, 16 bytes, see below

padding :: Random data, 0 or more bytes.
           Total message length must be 65535 bytes or less.
           Alice and Bob will use the padding data in the KDF for message 3 part 1.
           It is authenticated so that any tampering will cause the
           next message to fail.

Notes

  • Alice doit valider que la clé éphémère de Bob est un point valide sur la courbe ici.

  • Le padding devrait être limité à une quantité raisonnable. Alice peut rejeter les connexions avec un padding excessif. Alice spécifiera ses options de padding dans le message 3. Directives min/max à déterminer. Taille aléatoire de 0 à 31 octets minimum ? (Distribution à déterminer, voir Annexe A.)

  • En cas d’erreur, y compris AEAD, DH, timestamp, replay apparent, ou échec de validation de clé, Alice doit arrêter tout traitement de message supplémentaire et fermer la connexion sans répondre. Ceci devrait être une fermeture anormale (TCP RST).

  • Pour faciliter l’établissement rapide de la liaison, les implémentations doivent s’assurer que Bob met en mémoire tampon puis vide l’intégralité du contenu du premier message d’un coup, y compris le remplissage. Ceci augmente la probabilité que les données soient contenues dans un seul paquet TCP (sauf si segmentées par l’OS ou les middleboxes), et reçues d’un coup par Alice. C’est également pour l’efficacité et pour assurer l’efficacité du remplissage aléatoire.

  • Alice doit faire échouer la connexion si des données entrantes subsistent après validation du message 2 et lecture du padding. Il ne devrait y avoir aucune donnée supplémentaire de Bob, car Alice n’a pas encore répondu avec le message 3.

Bloc d’options : Note : Tous les champs sont en big-endian.


+----+----+----+----+----+----+----+----+
| Rsvd(0) | padLen  |   Reserved (0)    |
+----+----+----+----+----+----+----+----+
|        tsB        |   Reserved (0)    |
+----+----+----+----+----+----+----+----+

Reserved :: 10 bytes total, set to 0 for compatibility with future options

padLen :: 2 bytes, big endian, length of the padding, 0 or more
          Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
          (Distribution to be determined, see Appendix A.)

tsB :: 4 bytes, big endian, Unix timestamp, unsigned seconds.
       Wraps around in 2106

Notes

  • Alice doit rejeter les connexions où la valeur d’horodatage est trop éloignée de l’heure actuelle. Appelons le delta de temps maximum “D”. Alice doit maintenir un cache local des valeurs de handshake précédemment utilisées et rejeter les doublons, pour prévenir les attaques par rejeu. Les valeurs dans le cache doivent avoir une durée de vie d’au moins 2*D. Les valeurs de cache dépendent de l’implémentation, cependant la valeur Y de 32 octets (ou son équivalent chiffré) peut être utilisée.

Issues

  • Inclure les options de padding min/max ici ?

Encryption for for handshake message 3 part 1, using message 2 KDF)


// take h saved from message 2 KDF
// MixHash(ciphertext)
h = SHA256(h || 24 byte encrypted payload from message 2)

// MixHash(padding)
// Only if padding length is nonzero
h = SHA256(h || random padding from message 2)
// h is used as the associated data for the AEAD in message 3 part 1, below

This is the "s" message pattern:

Define s = Alice's static public key, 32 bytes

// EncryptAndHash(s.publickey)
// EncryptWithAd(h, s.publickey)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// k is from handshake message 1
// n is 1
ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, s.publickey)
// MixHash(ciphertext)
// || below means append
h = SHA256(h || ciphertext);

// h is used as the associated data for the AEAD in message 3 part 2

End of "s" message pattern.

Key Derivation Function (KDF) (for handshake message 3 part 2)


This is the "se" message pattern:

// DH(s, re) == DH(e, rs)
Define input_key_material = 32 byte DH result of Alice's static key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Bob's ephemeral key in memory, no longer needed
// Alice:
re = (all zeros)
// Bob:
e(public and private) = (all zeros)

// MixKey(DH())

Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)

// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck =       HMAC-SHA256(temp_key, byte(0x01)).

// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k =        HMAC-SHA256(temp_key, ck || byte(0x02)).

// h from message 3 part 1 is used as the associated data for the AEAD in message 3 part 2

// EncryptAndHash(payload)
// EncryptWithAd(h, payload)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// n is 0
ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, payload)
// MixHash(ciphertext)
// || below means append
h = SHA256(h || ciphertext);

// retain the chaining key ck for the data phase KDF
// retain the hash h for the data phase Additional Symmetric Key (SipHash) KDF

End of "se" message pattern.

// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)

3) SessionConfirmed

Alice envoie à Bob.

Contenu Noise : clé statique d’Alice Charge utile Noise : RouterInfo d’Alice et remplissage aléatoire Charge utile non-noise : aucune

(Propriétés de Sécurité de la Charge Utile)

XK(s, rs):           Authentication   Confidentiality
  -> s, se                  2                5

  Authentication: 2.
  Sender authentication resistant to key-compromise impersonation (KCI).  The
  sender authentication is based on an ephemeral-static DH ("es" or "se")
  between the sender's static key pair and the recipient's ephemeral key
  pair.  Assuming the corresponding private keys are secure, this
  authentication cannot be forged.

  Confidentiality: 5.
  Encryption to a known recipient, strong forward secrecy.  This payload is
  encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
  DH with the recipient's static key pair.  Assuming the ephemeral private
  keys are secure, and the recipient is not being actively impersonated by an
  attacker that has stolen its static private key, this payload cannot be
  decrypted.

  "s": Alice writes her static public key from the s variable into the
  message buffer, encrypting it, and hashes the output along with the old h
  to derive a new h.

  "se": A DH is performed between the Alice's static key pair and the Bob's
  ephemeral key pair.  The result is hashed along with the old ck to derive a
  new ck and k, and n is set to zero.

Ceci contient deux trames ChaChaPoly. La première est la clé publique statique chiffrée d’Alice. La seconde est la charge utile Noise : le RouterInfo chiffré d’Alice, les options facultatives et le remplissage optionnel. Elles utilisent des clés différentes, car la fonction MixKey() est appelée entre les deux.

Contenu brut :

+----+----+----+----+----+----+----+----+
|                                       |
+   ChaChaPoly frame (48 bytes)         +
|   Encrypted and authenticated         |
+   Alice static key S                  +
|      (32 bytes)                       |
+                                       +
|     k defined in KDF for message 2    |
+     n = 1                             +
|     see KDF for associated data       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|                                       |
+     Length specified in message 1     +
|                                       |
+   ChaChaPoly frame                    +
|   Encrypted and authenticated         |
+                                       +
|       Alice RouterInfo                |
+       using block format 2            +
|       Alice Options (optional)        |
+       using block format 1            +
|       Arbitrary padding               |
+       using block format 254          +
|                                       |
+                                       +
| k defined in KDF for message 3 part 2 |
+     n = 0                             +
|     see KDF for associated data       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian
     inside 48 byte ChaChaPoly frame

Données non chiffrées (tags d’authentification Poly1305 non affichés) :

+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|              S                        |
+       Alice static key                +
|          (32 bytes)                   |
+                                       +
|                                       |
+                                       +
+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|                                       |
+                                       +
|       Alice RouterInfo block          |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+
|                                       |
+       Optional Options block          +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+
|                                       |
+       Optional Padding block          +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

S :: 32 bytes, Alice's X25519 static key, little endian

1) DPI en ligne

  • Bob doit effectuer la validation habituelle des Router Info. S’assurer que le type de signature est pris en charge, vérifier la signature, vérifier que l’horodatage est dans les limites, et toute autre vérification nécessaire.

  • Bob doit vérifier que la clé statique d’Alice reçue dans la première trame correspond à la clé statique dans le Router Info. Bob doit d’abord rechercher dans le Router Info une Router Address NTCP ou NTCP2 avec une option de version (v) correspondante. Voir les sections Published Router Info et Unpublished Router Info ci-dessous.

  • Si Bob possède une version plus ancienne du RouterInfo d’Alice dans sa netdb, vérifier que la clé statique dans les informations de routeur est identique dans les deux, si présente, et si la version plus ancienne a moins de XXX d’ancienneté (voir le temps de rotation des clés ci-dessous)

  • Bob doit valider que la clé statique d’Alice est un point valide sur la courbe ici.

  • Les options doivent être incluses, pour spécifier les paramètres de padding.

  • En cas d’erreur, y compris une défaillance de validation AEAD, RI, DH, timestamp, ou de clé, Bob doit arrêter le traitement des messages et fermer la connexion sans répondre. Ceci devrait être une fermeture anormale (TCP RST).

  • Pour faciliter l’établissement rapide de la connexion, les implémentations doivent s’assurer qu’Alice met en mémoire tampon puis vide l’intégralité du contenu du troisième message d’un coup, incluant les deux trames AEAD. Cela augmente la probabilité que les données soient contenues dans un seul paquet TCP (sauf segmentation par l’OS ou les middleboxes), et reçues d’un coup par Bob. C’est également pour l’efficacité et pour garantir l’efficacité du padding aléatoire.

  • Longueur de la trame de la partie 2 du message 3 : La longueur de cette trame (MAC inclus) est envoyée par Alice dans le message 1. Voir ce message pour des notes importantes concernant l’allocation d’un espace suffisant pour le padding.

  • Contenu de la trame de la partie 2 du message 3 : Le format de cette trame est le même que le format des trames de la phase de données, sauf que la longueur de la trame est envoyée par Alice dans le message 1. Voir ci-dessous pour le format des trames de la phase de données. La trame doit contenir 1 à 3 blocs dans l’ordre suivant :

    1. Bloc Router Info d’Alice (obligatoire)
    2. Bloc d’options (optionnel)
    3. Bloc de remplissage (optionnel) Cette trame ne doit jamais contenir aucun autre type de bloc.
  • Le padding de la partie 2 du message 3 n’est pas requis si Alice ajoute une trame de phase de données (contenant optionnellement du padding) à la fin du message 3 et envoie les deux à la fois, car cela apparaîtra comme un grand flux d’octets pour un observateur. Comme Alice aura généralement, mais pas toujours, un message I2NP à envoyer à Bob (c’est pourquoi elle s’est connectée à lui), c’est l’implémentation recommandée, pour l’efficacité et pour assurer l’efficacité du padding aléatoire.

  • La longueur totale des deux trames AEAD du Message 3 (parties 1 et 2) est de 65535 octets ; la partie 1 fait 48 octets donc la longueur maximale de trame de la partie 2 est de 65487 ; la longueur maximale de texte en clair de la partie 2, MAC exclu, est de 65471.

Key Derivation Function (KDF) (for data phase)

La phase de données utilise une entrée de données associées de longueur zéro.

Le KDF génère deux clés de chiffrement k_ab et k_ba à partir de la clé de chaînage ck, en utilisant HMAC-SHA256(key, data) tel que défini dans RFC-2104. Il s’agit de la fonction Split(), exactement telle que définie dans la spécification Noise.


ck = from handshake phase

// k_ab, k_ba = HKDF(ck, zerolen)
// ask_master = HKDF(ck, zerolen, info="ask")

// zerolen is a zero-length byte array
temp_key = HMAC-SHA256(ck, zerolen)
// overwrite the chaining key in memory, no longer needed
ck = (all zeros)

// Output 1
// cipher key, for Alice transmits to Bob (Noise doesn't make clear which is which, but Java code does)
k_ab =   HMAC-SHA256(temp_key, byte(0x01)).

// Output 2
// cipher key, for Bob transmits to Alice (Noise doesn't make clear which is which, but Java code does)
k_ba =   HMAC-SHA256(temp_key, k_ab || byte(0x02)).


KDF for SipHash for length field:
Generate an Additional Symmetric Key (ask) for SipHash
SipHash uses two 8-byte keys (big endian) and 8 byte IV for first data.

// "ask" is 3 bytes, US-ASCII, no null termination
ask_master = HMAC-SHA256(temp_key, "ask" || byte(0x01))
// sip_master = HKDF(ask_master, h || "siphash")
// "siphash" is 7 bytes, US-ASCII, no null termination
// overwrite previous temp_key in memory
// h is from KDF for message 3 part 2
temp_key = HMAC-SHA256(ask_master, h || "siphash")
// overwrite ask_master in memory, no longer needed
ask_master = (all zeros)
sip_master = HMAC-SHA256(temp_key, byte(0x01))

Alice to Bob SipHash k1, k2, IV:
// sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen)
// overwrite previous temp_key in memory
temp_key = HMAC-SHA256(sip_master, zerolen)
// overwrite sip_master in memory, no longer needed
sip_master = (all zeros)

sipkeys_ab = HMAC-SHA256(temp_key, byte(0x01)).
sipk1_ab = sipkeys_ab[0:7], little endian
sipk2_ab = sipkeys_ab[8:15], little endian
sipiv_ab = sipkeys_ab[16:23]

Bob to Alice SipHash k1, k2, IV:

sipkeys_ba = HMAC-SHA256(temp_key, sipkeys_ab || byte(0x02)).
sipk1_ba = sipkeys_ba[0:7], little endian
sipk2_ba = sipkeys_ba[8:15], little endian
sipiv_ba = sipkeys_ba[16:23]

// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)

4) Data Phase

Payload Noise : Comme défini ci-dessous, incluant un remplissage aléatoire Payload non-Noise : aucun

À partir de la 2e partie du message 3, tous les messages sont à l’intérieur d’une “frame” ChaChaPoly authentifiée et chiffrée avec une longueur obfusquée de deux octets en préfixe. Tout le padding se trouve à l’intérieur de la frame. À l’intérieur de la frame se trouve un format standard avec zéro ou plusieurs “blocs”. Chaque bloc a un type d’un octet et une longueur de deux octets. Les types incluent date/heure, message I2NP, options, terminaison et padding.

Note : Bob peut, mais n’est pas obligé, d’envoyer son RouterInfo à Alice comme premier message à Alice dans la phase de données.

(Propriétés de sécurité de la charge utile)

XK(s, rs):           Authentication   Confidentiality
  <-                        2                5
  ->                        2                5

  Authentication: 2.
  Sender authentication resistant to key-compromise impersonation (KCI).
  The sender authentication is based on an ephemeral-static DH ("es" or "se")
  between the sender's static key pair and the recipient's ephemeral key pair.
  Assuming the corresponding private keys are secure, this authentication cannot be forged.

  Confidentiality: 5.
  Encryption to a known recipient, strong forward secrecy.
  This payload is encrypted based on an ephemeral-ephemeral DH as well as
  an ephemeral-static DH with the recipient's static key pair.
  Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
  by an attacker that has stolen its static private key, this payload cannot be decrypted.

2) DPI hors ligne

  • Pour des raisons d’efficacité et afin de minimiser l’identification du champ de longueur, les implémentations doivent s’assurer que l’expéditeur met en mémoire tampon puis vide entièrement le contenu des messages de données en une seule fois, y compris le champ de longueur et la trame AEAD. Cela augmente la probabilité que les données soient contenues dans un seul paquet TCP (sauf segmentation par l’OS ou les middleboxes), et reçues d’un coup par l’autre partie. Ceci est également pour des raisons d’efficacité et pour assurer l’efficacité du padding aléatoire.

  • Le routeur peut choisir de terminer la session en cas d’erreur AEAD, ou peut continuer à tenter de communiquer. S’il continue, le routeur devrait terminer après des erreurs répétées.

SipHash obfuscated length

Référence : SipHash

Une fois que les deux côtés ont terminé la négociation, ils transfèrent des charges utiles qui sont ensuite chiffrées et authentifiées dans des “trames” ChaChaPoly.

Chaque trame est précédée d’une longueur de deux octets, big endian. Cette longueur spécifie le nombre d’octets de trame chiffrés qui suivent, incluant le MAC. Pour éviter de transmettre des champs de longueur identifiables dans le flux, la longueur de la trame est masquée par XOR avec un masque dérivé de SipHash, tel qu’initialisé depuis la KDF de phase de données. Notez que les deux directions ont des clés SipHash et des IV uniques provenant de la KDF.

    sipk1, sipk2 = The SipHash keys from the KDF.  (two 8-byte long integers)
    IV[0] = sipiv = The SipHash IV from the KDF. (8 bytes)
    length is big endian.
    For each frame:
      IV[n] = SipHash-2-4(sipk1, sipk2, IV[n-1])
      Mask[n] = First 2 bytes of IV[n]
      obfuscatedLength = length ^ Mask[n]

    The first length output will be XORed with with IV[1].

Le récepteur possède les clés SipHash et IV identiques. Le décodage de la longueur se fait en dérivant le masque utilisé pour obscurcir la longueur et en appliquant un XOR au digest tronqué pour obtenir la longueur de la trame. La longueur de la trame correspond à la longueur totale de la trame chiffrée incluant le MAC.

Travaux futurs

  • Si vous utilisez une fonction de bibliothèque SipHash qui retourne un entier long non signé, utilisez les deux octets les moins significatifs comme Mask. Convertissez l’entier long vers le prochain IV en little endian.

Chiffrement Authentifié

+----+----+----+----+----+----+----+----+
|obf size |                             |
+----+----+                             +
|                                       |
+   ChaChaPoly frame                    +
|   Encrypted and authenticated         |
+   key is k_ab for Alice to Bob        +
|   key is k_ba for Bob to Alice        |
+   as defined in KDF for data phase    +
|   n starts at 0 and increments        |
+   for each frame in that direction    +
|   no associated data                  |
+   16 bytes minimum                    +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

obf size :: 2 bytes length obfuscated with SipHash
            when de-obfuscated: 16 - 65535

Minimum size including length field is 18 bytes.
Maximum size including length field is 65537 bytes.
Obfuscated length is 2 bytes.
Maximum ChaChaPoly frame is 65535 bytes.

ChaCha20/Poly1305

Il y a zéro ou plusieurs blocs dans la trame chiffrée. Chaque bloc contient un identifiant d’un octet, une longueur de deux octets, et zéro ou plusieurs octets de données.

Pour l’extensibilité, les récepteurs doivent ignorer les blocs avec des identifiants inconnus et les traiter comme du remplissage.

Les données chiffrées font au maximum 65535 octets, incluant un en-tête d’authentification de 16 octets, donc les données non chiffrées font au maximum 65519 octets.

(Tag d’authentification Poly1305 non affiché) :

+----+----+----+----+----+----+----+----+
|blk |  size   |       data             |
+----+----+----+                        +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+
|blk |  size   |       data             |
+----+----+----+                        +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+
~               .   .   .               ~

blk :: 1 byte
       0 for datetime
       1 for options
       2 for RouterInfo
       3 for I2NP message
       4 for termination
       224-253 reserved for experimental features
       254 for padding
       255 reserved for future extension
size :: 2 bytes, big endian, size of data to follow, 0 - 65516
data :: the data

Maximum ChaChaPoly frame is 65535 bytes.
Poly1305 tag is 16 bytes
Maximum total block size is 65519 bytes
Maximum single block size is 65519 bytes
Block type is 1 byte
Block length is 2 bytes
Maximum single block data size is 65516 bytes.

Block Ordering Rules

Dans le message de handshake 3 partie 2, l’ordre doit être : RouterInfo, suivi des Options si présentes, suivi du Padding si présent. Aucun autre bloc n’est autorisé.

Dans la phase de données, l’ordre n’est pas spécifié, sauf pour les exigences suivantes : Le Padding, s’il est présent, doit être le dernier bloc. La Termination, si elle est présente, doit être le dernier bloc sauf pour le Padding.

Il peut y avoir plusieurs blocs I2NP dans une seule trame. Plusieurs blocs de remplissage ne sont pas autorisés dans une seule trame. D’autres types de blocs n’auront probablement pas plusieurs blocs dans une seule trame, mais ce n’est pas interdit.

Gestion des erreurs AEAD

Cas particulier pour la synchronisation temporelle :

+----+----+----+----+----+----+----+
| 0  |    4    |     timestamp     |
+----+----+----+----+----+----+----+

blk :: 0
size :: 2 bytes, big endian, value = 4
timestamp :: Unix timestamp, unsigned seconds.
             Wraps around in 2106

Fonction de dérivation de clé (KDF) (pour le message 1 de handshake)

Passer les options mises à jour. Les options incluent : Remplissage minimum et maximum.

Le bloc d’options aura une longueur variable.

+----+----+----+----+----+----+----+----+
| 1  |  size   |tmin|tmax|rmin|rmax|tdmy|
+----+----+----+----+----+----+----+----+
|tdmy|  rdmy   |  tdelay |  rdelay |    |
~----+----+----+----+----+----+----+    ~
|              more_options             |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

blk :: 1
size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum

tmin, tmax, rmin, rmax :: requested padding limits
    tmin and rmin are for desired resistance to traffic analysis.
    tmax and rmax are for bandwidth limits.
    tmin and tmax are the transmit limits for the router sending this options block.
    rmin and rmax are the receive limits for the router sending this options block.
    Each is a 4.4 fixed-point float representing 0 to 15.9375
    (or think of it as an unsigned 8-bit integer divided by 16.0).
    This is the ratio of padding to data. Examples:
    Value of 0x00 means no padding
    Value of 0x01 means add 6 percent padding
    Value of 0x10 means add 100 percent padding
    Value of 0x80 means add 800 percent (8x) padding
    Alice and Bob will negotiate the minimum and maximum in each direction.
    These are guidelines, there is no enforcement.
    Sender should honor receiver's maximum.
    Sender may or may not honor receiver's minimum, within bandwidth constraints.

tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average
rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average
tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average
rdelay: Requested intra-message delay, 2 bytes big endian, msec average

Padding distribution specified as additional parameters?
Random delay specified as additional parameters?

more_options :: Format TBD

1) SessionRequest

  • Le format des options est à déterminer.
  • La négociation des options est à déterminer.

RouterInfo

Transmettre les RouterInfo d’Alice à Bob. Utilisé dans le message de handshake 3 partie 2. Transmettre les RouterInfo d’Alice à Bob, ou ceux de Bob à Alice. Utilisé optionnellement dans la phase de données.

+----+----+----+----+----+----+----+----+
| 2  |  size   |flg |    RouterInfo     |
+----+----+----+----+                   +
| (Alice RI in handshake msg 3 part 2)  |
~ (Alice, Bob, or third-party           ~
|  RI in data phase)                    |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

blk :: 2
size :: 2 bytes, big endian, size of flag + router info to follow
flg :: 1 byte flags
       bit order: 76543210
       bit 0: 0 for local store, 1 for flood request
       bits 7-1: Unused, set to 0 for future compatibility
routerinfo :: Alice's or Bob's RouterInfo

Notes

  • Lorsqu’utilisé dans la phase de données, le destinataire (Alice ou Bob) doit valider que c’est le même Router Hash que celui envoyé à l’origine (pour Alice) ou envoyé à (pour Bob). Ensuite, le traiter comme un message I2NP DatabaseStore local. Valider la signature, valider l’horodatage plus récent, et stocker dans la netdb locale. Si le bit de flag 0 est à 1, et que la partie réceptrice est floodfill, le traiter comme un message DatabaseStore avec un token de réponse non-zéro, et le propager aux floodfills les plus proches.

  • Les Router Info ne sont PAS compressées avec gzip (contrairement à un DatabaseStore Message, où elles le sont)

  • Le flooding ne doit pas être demandé à moins qu’il y ait des RouterAddresses publiées dans le RouterInfo. Le router récepteur ne doit pas effectuer le flood du RouterInfo à moins qu’il contienne des RouterAddresses publiées.

  • Les implémenteurs doivent s’assurer que lors de la lecture d’un bloc, des données malformées ou malveillantes ne provoqueront pas de débordement de lecture dans le bloc suivant.

  • Ce protocole ne fournit pas d’accusé de réception indiquant que le RouterInfo a été reçu, stocké ou diffusé (que ce soit dans la phase de négociation ou de données). Si un accusé de réception est souhaité, et que le destinataire est floodfill, l’expéditeur devrait plutôt envoyer un DatabaseStoreMessage I2NP standard avec un jeton de réponse.

Issues

  • Pourrait également être utilisé dans la phase de données, au lieu d’un I2NP DatabaseStoreMessage. Par exemple, Bob pourrait l’utiliser pour initier la phase de données.

  • Est-il autorisé que ceci contienne le RI pour des routers autres que l’expéditeur, comme remplacement général des DatabaseStoreMessages, par exemple pour le flooding par les floodfills ?

Fonction de dérivation de clé (KDF) (pour le message de handshake 2 et la partie 1 du message 3)

Un seul message I2NP avec un en-tête modifié. Les messages I2NP ne peuvent pas être fragmentés entre les blocs ou entre les trames ChaChaPoly.

Ceci utilise les 9 premiers octets de l’en-tête NTCP I2NP standard, et supprime les 7 derniers octets de l’en-tête, comme suit : tronquer l’expiration de 8 à 4 octets, supprimer la longueur de 2 octets (utiliser la taille du bloc - 9), et supprimer la somme de contrôle SHA256 d’un octet.

+----+----+----+----+----+----+----+----+
| 3  |  size   |type|    msg id         |
+----+----+----+----+----+----+----+----+
|   short exp       |     message       |
+----+----+----+----+                   +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

blk :: 3
size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
        I2NP message body size is (size - 9).
type :: 1 byte, I2NP msg type, see I2NP spec
msg id :: 4 bytes, big endian, I2NP message ID
short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
             Wraps around in 2106
message :: I2NP message body

Notes

  • Les implémenteurs doivent s’assurer que lors de la lecture d’un bloc, des données malformées ou malveillantes ne provoqueront pas de débordement de lecture dans le bloc suivant.

2) SessionCreated

Noise recommande un message de terminaison explicite. Le NTCP original n’en a pas. Interrompre la connexion. Ceci doit être le dernier bloc non-padding dans la trame.

+----+----+----+----+----+----+----+----+
| 4  |  size   |    valid data frames   |
+----+----+----+----+----+----+----+----+
    received   | rsn|     addl data     |
+----+----+----+----+                   +
~               .   .   .               ~
+----+----+----+----+----+----+----+----+

blk :: 4
size :: 2 bytes, big endian, value = 9 or more
valid data frames received :: The number of valid AEAD data phase frames received
                              (current receive nonce value)
                              0 if error occurs in handshake phase
                              8 bytes, big endian
rsn :: reason, 1 byte:
       0: normal close or unspecified
       1: termination received
       2: idle timeout
       3: router shutdown
       4: data phase AEAD failure
       5: incompatible options
       6: incompatible signature type
       7: clock skew
       8: padding violation
       9: AEAD framing error
       10: payload format error
       11: message 1 error
       12: message 2 error
       13: message 3 error
       14: intra-frame read timeout
       15: RI signature verification fail
       16: s parameter missing, invalid, or mismatched in RouterInfo
       17: banned
addl data :: optional, 0 or more bytes, for future expansion, debugging,
             or reason text.
             Format unspecified and may vary based on reason code.

Notes

Toutes les raisons peuvent ne pas être réellement utilisées, cela dépend de l’implémentation. Les échecs de handshake entraîneront généralement une fermeture avec TCP RST à la place. Voir les notes dans les sections de messages de handshake ci-dessus. Les raisons supplémentaires listées sont pour la cohérence, la journalisation, le débogage, ou si la politique change.

Padding

Ceci est pour le padding à l’intérieur des trames AEAD. Le padding pour les messages 1 et 2 se trouve à l’extérieur des trames AEAD. Tout le padding pour le message 3 et la phase de données se trouve à l’intérieur des trames AEAD.

Le padding à l’intérieur d’AEAD doit approximativement respecter les paramètres négociés. Bob a envoyé ses paramètres tx/rx min/max demandés dans le message 2. Alice a envoyé ses paramètres tx/rx min/max demandés dans le message 3. Des options mises à jour peuvent être envoyées pendant la phase de données. Voir les informations sur le bloc d’options ci-dessus.

Si présent, celui-ci doit être le dernier bloc de la trame.

+----+----+----+----+----+----+----+----+
|254 |  size   |      padding           |
+----+----+----+                        +
|                                       |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

blk :: 254
size :: 2 bytes, big endian, size of padding to follow
padding :: random data

Notes

  • Stratégies de remplissage à déterminer.
  • Remplissage minimum à déterminer.
  • Les trames de remplissage uniquement sont autorisées.
  • Valeurs par défaut du remplissage à déterminer.
  • Voir le bloc d’options pour la négociation des paramètres de remplissage
  • Voir le bloc d’options pour les paramètres de remplissage min/max
  • Noise limite les messages à 64 Ko. Si plus de remplissage est nécessaire, envoyer plusieurs trames.
  • La réponse du router en cas de violation du remplissage négocié dépend de l’implémentation.

Other block types

Les implémentations doivent ignorer les types de blocs inconnus pour assurer la compatibilité ascendante, sauf dans la partie 2 du message 3, où les blocs inconnus ne sont pas autorisés.

Future work

  • La longueur du padding doit soit être décidée au cas par cas avec des estimations de la distribution des longueurs, soit des délais aléatoires doivent être ajoutés. Ces contre-mesures doivent être incluses pour résister à la DPI, car les tailles des messages révéleraient autrement que le trafic I2P est transporté par le protocole de transport. Le schéma de padding exact est un domaine de travail futur, l’Annexe A fournit plus d’informations sur le sujet.

5) Termination

Les connexions peuvent être interrompues via une fermeture normale ou anormale du socket TCP, ou, comme Noise le recommande, via un message de terminaison explicite. Le message de terminaison explicite est défini dans la phase de données ci-dessus.

Lors de toute terminaison normale ou anormale, les routers doivent remettre à zéro toute donnée éphémère en mémoire, y compris les clés éphémères de handshake, les clés cryptographiques symétriques, et les informations associées.

Published Router Info

Chiffrement pour la partie 1 du message 3 de handshake, en utilisant le KDF du message 2)

L’adresse RouterAddress publiée (partie du RouterInfo) aura un identifiant de protocole soit “NTCP” soit “NTCP2”.

La RouterAddress doit contenir les options “host” et “port”, comme dans le protocole NTCP actuel.

La RouterAddress doit contenir trois options pour indiquer la prise en charge NTCP2 :

  • s=(Clé Base64) La clé publique statique Noise actuelle (s) pour cette RouterAddress. Encodée en Base 64 en utilisant l’alphabet Base 64 standard I2P. 32 octets en binaire, 44 octets encodés en Base 64, clé publique X25519 en little-endian.

  • i=(Base64 IV) L’IV actuel pour chiffrer la valeur X dans le message 1 pour cette RouterAddress. Encodé en Base 64 en utilisant l’alphabet Base 64 standard d’I2P. 16 octets en binaire, 24 octets encodé en Base 64, big-endian.

  • v=2 La version actuelle (2). Lorsque publié comme “NTCP”, un support additionnel pour la version 1 est implicite. Le support pour les versions futures se fera avec des valeurs séparées par des virgules, par ex. v=2,3 L’implémentation doit vérifier la compatibilité, incluant plusieurs versions si une virgule est présente. Les versions séparées par des virgules doivent être dans l’ordre numérique.

Alice doit vérifier que les trois options sont présentes et valides avant de se connecter en utilisant le protocole NTCP2.

Lorsqu’il est publié comme “NTCP” avec les options “s”, “i”, et “v”, le router doit accepter les connexions entrantes sur cet hôte et ce port pour les protocoles NTCP et NTCP2, et détecter automatiquement la version du protocole.

Lorsqu’il est publié comme “NTCP2” avec les options “s”, “i” et “v”, le router accepte les connexions entrantes sur cet hôte et ce port pour le protocole NTCP2 uniquement.

Si un router prend en charge les connexions NTCP1 et NTCP2 mais n’implémente pas la détection automatique de version pour les connexions entrantes, il doit annoncer à la fois les adresses “NTCP” et “NTCP2”, et inclure les options NTCP2 dans l’adresse “NTCP2” uniquement. Le router devrait définir une valeur de coût plus faible (priorité plus élevée) dans l’adresse “NTCP2” que dans l’adresse “NTCP”, de sorte que NTCP2 soit préféré.

Si plusieurs RouterAddresses NTCP2 (soit comme “NTCP” ou “NTCP2”) sont publiées dans le même RouterInfo (pour des adresses IP ou ports supplémentaires), toutes les adresses spécifiant le même port doivent contenir les options et valeurs NTCP2 identiques. En particulier, toutes doivent contenir la même clé statique et le même iv.

Fonction de Dérivation de Clé (KDF) (pour le message de handshake 3 partie 2)

Si Alice ne publie pas son adresse NTCP2 (comme “NTCP” ou “NTCP2”) pour les connexions entrantes, elle doit publier une adresse router “NTCP2” contenant uniquement sa clé statique et sa version NTCP2, afin que Bob puisse valider la clé après avoir reçu le RouterInfo d’Alice dans le message 3 partie 2.

  • s=(Clé Base64) Comme défini ci-dessus pour les adresses publiées.

  • v=2 Comme défini ci-dessus pour les adresses publiées.

Cette adresse de routeur ne contiendra pas les options “i”, “host” ou “port”, car elles ne sont pas requises pour les connexions NTCP2 sortantes. Le coût publié pour cette adresse n’a pas strictement d’importance, puisqu’elle est uniquement entrante ; cependant, il peut être utile aux autres routeurs que le coût soit défini plus élevé (priorité plus faible) que les autres adresses. La valeur suggérée est 14.

Alice peut également simplement ajouter les options “s” et “v” à une adresse “NTCP” publiée existante.

3) SessionConfirmed

En raison de la mise en cache des RouterInfos, les routers ne doivent pas faire la rotation de la clé publique statique ou de l’IV pendant que le router est en fonctionnement, que ce soit dans une adresse publiée ou non. Les routers doivent stocker de manière persistante cette clé et cet IV pour les réutiliser après un redémarrage immédiat, afin que les connexions entrantes continuent de fonctionner et que les temps de redémarrage ne soient pas exposés. Les routers doivent stocker de manière persistante, ou déterminer autrement, l’heure du dernier arrêt, afin que le temps d’arrêt précédent puisse être calculé au démarrage.

Sous réserve des préoccupations concernant l’exposition des temps de redémarrage, les routers peuvent faire tourner cette clé ou IV au démarrage si le router était précédemment arrêté pendant un certain temps (au moins quelques heures).

Si le router a des RouterAddresses NTCP2 publiées (comme NTCP ou NTCP2), le temps d’arrêt minimum avant la rotation devrait être beaucoup plus long, par exemple un mois, sauf si l’adresse IP locale a changé ou si le router effectue un “rekeys”.

Si le routeur a des SSU RouterAddresses publiées, mais pas NTCP2 (comme NTCP ou NTCP2), la durée minimale d’arrêt avant rotation devrait être plus longue, par exemple un jour, à moins que l’adresse IP locale ait changé ou que le routeur effectue un “rekeys”. Ceci s’applique même si l’adresse SSU publiée a des introducers.

Si le router n’a pas de RouterAddresses publiées (NTCP, NTCP2, ou SSU), le temps d’arrêt minimum avant la rotation peut être aussi court que deux heures, même si l’adresse IP change, à moins que le router ne fasse un “rekeys”.

Si le router “rekeys” vers un Router Hash différent, il devrait également générer une nouvelle clé noise et un nouvel IV.

Les implémentations doivent être conscientes que changer la clé publique statique ou l’IV empêchera les connexions NTCP2 entrantes des routeurs qui ont mis en cache un RouterInfo plus ancien. La publication de RouterInfo, la sélection des pairs de tunnel (incluant à la fois OBGW et le saut le plus proche IB), la sélection de tunnel zero-hop, la sélection de transport, et d’autres stratégies d’implémentation doivent prendre cela en compte.

La rotation d’IV est soumise aux mêmes règles que la rotation de clé, sauf que les IV ne sont présents que dans les RouterAddresses publiées, il n’y a donc pas d’IV pour les routeurs cachés ou protégés par un pare-feu. Si quelque chose change (version, clé, options ?) il est recommandé que l’IV change également.

Remarque : Le temps d’arrêt minimum avant la regénération des clés peut être modifié pour garantir la santé du réseau et empêcher le reseeding par un router arrêté pendant une durée modérée.

Identity Hiding

La déniabilité n’est pas un objectif. Voir l’aperçu ci-dessus.

Chaque motif se voit attribuer des propriétés décrivant la confidentialité fournie à la clé publique statique de l’initiateur, et à la clé publique statique du répondeur. Les hypothèses sous-jacentes sont que les clés privées éphémères sont sécurisées, et que les parties abandonnent l’établissement de liaison si elles reçoivent une clé publique statique de l’autre partie en laquelle elles n’ont pas confiance.

Cette section ne considère que la fuite d’identité à travers les champs de clé publique statique dans les échanges de clés. Bien sûr, les identités des participants Noise pourraient être exposées par d’autres moyens, notamment les champs de charge utile, l’analyse de trafic, ou les métadonnées telles que les adresses IP.

Alice : (8) Chiffré avec confidentialité persistante vers une partie authentifiée.

Bob : (3) Non transmis, mais un attaquant passif peut vérifier les candidats pour la clé privée du répondeur et déterminer si le candidat est correct.

Bob publie sa clé publique statique dans la netDb. Alice peut ou peut ne pas ?

Issues

  • Si Bob change sa clé statique, pourrait-il revenir à un motif “XX” ?

Framework de Protocole Noise

Lorsqu’il est publié comme “NTCP”, le router doit automatiquement détecter la version du protocole pour les connexions entrantes.

Cette détection dépend de l’implémentation, mais voici quelques conseils généraux.

Pour détecter la version d’une connexion NTCP entrante, Bob procède comme suit :

  • Attendre au moins 64 octets (taille minimale du message 1 NTCP2)

  • Si les données initiales reçues font 288 octets ou plus, la connexion entrante est en version 1.

  • Si moins de 288 octets, soit

  • Attendre un court moment pour recevoir plus de données (bonne stratégie avant l’adoption généralisée de NTCP2) si au moins 288 octets ont été reçus au total, c’est du NTCP 1.

  • Essayez les premières étapes du décodage en version 2, si cela échoue, attendez un court moment pour plus de données (bonne stratégie après l’adoption généralisée de NTCP2)

    - Decrypt the first 32 bytes (the X key)
      of the SessionRequest packet using AES-256 with key RH_B.
    
    - Verify a valid point on the curve.
      If it fails, wait a short time for more data for NTCP 1
    
    - Verify the AEAD frame.
      If it fails, wait a short time for more data for NTCP 1
    

Notez que des modifications ou des stratégies supplémentaires peuvent être recommandées si nous détectons des attaques actives de segmentation TCP sur NTCP 1.

Pour faciliter la détection rapide de version et la négociation, les implémentations doivent s’assurer qu’Alice met en mémoire tampon puis vide entièrement le contenu du premier message d’un coup, y compris le rembourrage. Cela augmente la probabilité que les données soient contenues dans un seul paquet TCP (sauf si segmentées par l’OS ou des middleboxes), et reçues d’un seul coup par Bob. C’est aussi pour l’efficacité et pour assurer l’efficacité du rembourrage aléatoire. Cela s’applique aux négociations NTCP et NTCP2.

Ajouts au Framework

  • Si Alice et Bob supportent tous les deux NTCP2, Alice devrait se connecter avec NTCP2.

  • Si Alice échoue à se connecter à Bob en utilisant NTCP2 pour quelque raison que ce soit, la connexion échoue. Alice ne peut pas réessayer en utilisant NTCP 1.

  • Retour au modèle XX si Bob change ses clés ? Cela nécessiterait un octet de type en préfixe ?

  • “Fall forward” vers le pattern KK si Alice se reconnecte, en supposant que Bob a encore sa clé statique ? Cela ne sauvegarde aucun aller-retour et utilise 4 tours DH comparé à 3 pour XK. Probablement pas.

  KK(s, rs):
    -> s
    <- s
    ...
    -> e, es, ss
    <- e, ee, se

Nouvelles primitives cryptographiques pour I2P

Cette section discute d’une attaque contre les schémas de bourrage typiques qui permet aux attaquants de découvrir la distribution de probabilité de la longueur des messages non bourrés, en observant uniquement la longueur des messages bourrés. Soit N une variable aléatoire décrivant le nombre d’octets non bourrés, et P de même pour le nombre d’octets de bourrage. La taille totale du message est alors N + P.

Supposons que pour une taille non remplie de n, au moins P_min(n) >= 0 et au plus P_max(n) >= P_min(n) octets de rembourrage sont ajoutés dans un schéma de rembourrage. Le schéma évident utilise un rembourrage de longueur P choisi uniformément au hasard :

Pr[P = p | N = n] = 1 / (P_max(n) - P_min(n)) if P_min(n) <= p <= P_max(n),
                    0                         otherwise.

Un schéma de remplissage naïf s’assurerait simplement que la taille du message rempli n’excède pas N_max :

P_max(n) = N_max - n, n <= N_max
P_min(n) = 0.

Cependant, cela divulgue des informations sur la longueur non rembourrée.

Un attaquant peut facilement estimer Pr[x <= N + P <= y], par exemple au moyen d’un histogramme.

  • À partir de cela, il peut aussi essayer d’estimer Pr[n_1 <= N <= n_2], en effet :
Pr[N + P = m] = Σ_n Pr[N = n] Pr[P = m - n | N = n].

Dans le schéma naïf,

Pr[N + P = m] = Σ_{n <= m} Pr[N = n] / (N_max - n).

C’est assez évident, comme c’était le cas avant de faire le calcul ci-dessus, que cela divulgue des informations sur Pr[N = n] : si la longueur des paquets est presque toujours supérieure à m, alors N + P <= m ne sera presque jamais observé. Ce n’est cependant pas le problème le plus important, bien que pouvoir observer la longueur minimale du message puisse être considéré comme un problème en soi.

Un problème plus important est qu’il est possible de déterminer Pr[N = n] exactement :

Pr[N + P = m] - Pr[N + P = m-1] = Pr[N = m] / (N_max - m),

c’est-à-dire

Pr[N = n] = (N_max - n)(Pr[N + P = n] - Pr[N + P = n - 1])

Pour distinguer NTCP2, alors, l’attaquant peut utiliser n’importe laquelle des méthodes suivantes :

  • Estimer Pr[kB <= N <= (k + 1)B - 1] pour les entiers positifs k. Ce sera toujours zéro pour NTCP2.

  • Estimer Pr[N = kB] et comparer avec un profil I2P standard.

Cette attaque simple détruit donc partiellement l’objectif du padding, qui tente d’obscurcir la distribution de taille des messages non paddés. Le nombre de messages que l’attaquant doit observer pour distinguer le protocole dépend de la précision désirée et des tailles minimale et maximale des messages non paddés qui se produisent en pratique. Notez qu’il est facile pour l’attaquant de rassembler de nombreux messages, puisqu’il peut utiliser tout le trafic envoyé depuis et vers le port particulier que la cible utilise.

Dans certaines formes (par exemple l’estimation de Pr[kB <= N <= (k + 1)B - 1]) l’attaque ne nécessite que quelques octets de mémoire (un entier suffit) et on pourrait soutenir qu’une telle attaque pourrait être incluse dans de nombreux frameworks DPI légèrement plus avancés mais néanmoins standard.

Cette proposition suggère d’utiliser l’une des contre-mesures suivantes :

  • Développer un schéma de padding alternatif qui prend en compte la distribution (estimée) de N en utilisant une distribution de longueur de padding non-uniforme. Un bon schéma de padding nécessiterait probablement de maintenir un histogramme du nombre de blocs par message.

  • Ajouter des délais aléatoires entre les fragments (de taille aléatoire) des messages.

La deuxième option est généralement préférée, car elle peut être utilisée simultanément comme contre-mesure contre l’analyse de flux. Cependant, de tels délais peuvent être hors du champ d’application du protocole NTCP2, de sorte que la première option, qui est également plus facile à implémenter, peut être préférée à la place.

Estimation de la surcharge de traitement

Résistance à l’inspection approfondie de paquets basée sur le timing (les délais/temporisations entre messages peuvent dépendre de l’implémentation ; les délais intra-message peuvent être introduits à tout moment, y compris avant l’envoi du padding aléatoire, par exemple). Les délais artificiels (ce qu’obfs4 appelle IAT ou temps inter-arrivée) sont indépendants du protocole lui-même.