Poignée de main d'authentification
Une étape commune utilisée à l'identique, au bit près, par le port client et le port Raft du cluster. Une fois la connexion établie (après la poignée de main TLS si TLS est utilisé), le serveur parle en premier et envoie un challenge. C'est un échange de texte de deux lignes, délimité par des retours à la ligne (\n), effectué une fois par connexion.
La seule chose qui diffère selon le port est l'ensemble de jetons utilisé pour la vérification — le port client vérifie par rapport à client_tokens, le port Raft par rapport à cluster_tokens. Voir Connexion et authentification (Cluster) pour les règles de jeton spécifiques au port Raft (quel jeton est envoyé, et comment faire tourner les jetons sans interruption de service).
Flux
1. Challenge (serveur → connecteur)
<hash> <nonce>\n par ex. SHA-256 aB3dEf_g\n| Champ | Contenu |
|---|---|
hash | Nom de l'algorithme de condensé. Actuellement toujours SHA-256, le serveur n'accepte rien d'autre |
nonce | Une valeur aléatoire base64url de 8 caractères. Le trâmage est délimité par des retours à la ligne, sa longueur pourrait donc croître plus tard — le connecteur doit traiter tout ce qui suit le premier espace comme le nonce |
2. Réponse (connecteur → serveur)
<digest>\n
digest = base64url_nopad( SHA-256( token_bytes ∥ nonce_bytes ) )(∥ est une concaténation d'octets — les octets ASCII de la chaîne du nonce sont ajoutés directement après les octets bruts du jeton)
- base64url est l'alphabet non paddé et compatible URL (
A–Z a–z 0–9 - _). Un condensé SHA-256 fait toujours 43 caractères. - Le serveur vérifie par une comparaison en temps constant avec toute la liste de jetons configurée — quel jeton a correspondu, ou jusqu'où une comparaison est allée, ne fuit jamais par le timing.
- Un serveur sans jeton configuré accepte un unique jeton vide
"". Dans ce cas, envoyerdigest = base64url(SHA-256(nonce))passe la vérification. L'étape de poignée de main elle-même ne peut jamais être sautée. - La ligne de réponse lue par le serveur est plafonnée à 256 octets.
3. Résultat
- Succès : le serveur n'envoie rien et bascule directement dans le protocole principal — le protocole de verrous à trames binaires sur le port client, ou le RPC à préfixe de longueur sur le port Raft. Vous pouvez envoyer la première requête aussitôt.
- Échec : le serveur envoie
E auth_failedpuis ferme la connexion. Si la connexion tombe ou qu'une ligne est malformée en cours de poignée de main, elle peut aussi simplement se fermer silencieusement sans trame d'erreur.
Terminologie
- Challenge-réponse — un schéma d'authentification où, au lieu d'envoyer directement le secret (jeton), le serveur pose un défi à usage unique et le connecteur prouve qu'il connaît le secret en renvoyant seulement la réponse.
- Nonce — un nombre utilisé une seule fois. Il change à chaque connexion, si bien qu'une réponse volée ne peut pas être réutilisée dans une attaque par rejeu (replay).
- Comparaison en temps constant (constant-time compare) — une comparaison qui prend toujours le même temps, indépendamment de jusqu'où elle a correspondu, fermant la porte aux attaques par timing qui pourraient sinon faire fuiter le secret.
- base64url — une variante de base64 n'utilisant qu'un alphabet compatible URL (
A–Z a–z 0–9 - _). Utilisée ici sans padding (=).