From cc392238f701c7ac7edad7dde36ad9227232ff62 Mon Sep 17 00:00:00 2001 From: neckfire Date: Thu, 16 Jul 2026 23:58:13 +0200 Subject: [PATCH] =?UTF-8?q?docs(netcode):=20findings=20AES-GCM=20=E2=80=94?= =?UTF-8?q?=20le=20client=20ferme=20syst=C3=A9matiquement=20(plaintext=20b?= =?UTF-8?q?Close)=20apr=C3=A8s=20notre=20r=C3=A9ponse=20au=20Hello=20;=20p?= =?UTF-8?q?istes=20restantes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NETCODE-RND.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/NETCODE-RND.md b/NETCODE-RND.md index 3e5dc49..1f0887f 100644 --- a/NETCODE-RND.md +++ b/NETCODE-RND.md @@ -137,3 +137,29 @@ keyé par la PSK** (SetEncryptionData/EnableEncryption d'UE) plutôt que du DTLS **Acquis réutilisables :** on passe le handshake + le Hello + l'EncryptionAck est accepté ; la PSK par user_id est branchée bout-en-bout (Vault → env → serveur). Le blocage net = chiffrement de la voie serveur post-ack. + +## MAJ (2026-07-16, nuit) — tentative AES-256-GCM keyé par la PSK + +Implémenté `AesGcmHandlerComponent` (`System.Security.Cryptography.AesGcm`, format +`[IV 12o][ciphertext][tag 16o]`), activé après l'EncryptionAck (ack en clair → activation → +Challenge chiffré). Corrigé aussi l'ordre du pipeline : **Incoming doit itérer en sens +INVERSE d'Outgoing** (`PacketHandler.Incoming_Internal`) — sinon, avec 2 composants actifs +(stateless + AES), le stateless tente de parser des octets chiffrés. (Les deux étaient en avant ; +n'avait jamais compté car un seul composant actif jusqu'ici.) + +**Observé (test live) :** notre Challenge part bien chiffré (`[AES] Outgoing 30o→58o`), mais le +client répond **toujours** par un **paquet plaintext de ~18 o** de structure constante +(`…41 00 XX FF 5F 00 00 0C`) = un **`bClose` du canal de contrôle**, jamais rien qui ressemble +à de l'AES (haute entropie ≥28o). **Le client ne chiffre jamais son côté.** + +**Conclusion :** quelle que soit notre réponse au `Hello` (challenge clair, chiffré AES, ou +tentative DTLS), le client **ferme systématiquement le canal de contrôle en clair** juste après. +L'AES-GCM tel qu'implémenté ne le fait pas basculer en chiffré. Pistes restantes (deep RE, non +tranchées) : (a) framing AES-GCM exact d'UE (schéma d'IV/nonce, AAD, position) ≠ notre IV aléatoire +préfixé ; (b) c'est bien du DTLS-handshake et le client attend un ServerHello DTLS ; (c) notre +réponse au Hello est incomplète (ordre/contenu des NMT) indépendamment du chiffrement. +Chaque test = ~4 min (CI + redeploy). Bugs serveur secondaires à corriger : `ConditionalCleanUp` +(stub) + `ArgumentOutOfRangeException` quand on vide un paquet trop court. + +**Décision : checkpoint.** Tout est commité/documenté. La suite = RE netcode profonde multi-session ; +et même résolue, ce n'est que le login — la simulation gameplay reste hors de portée réaliste.