nebino

TOTP : comment fonctionne le 2FA par code

20 octobre 2026

Les codes à six chiffres qui changent toutes les 30 secondes n’ont rien de magique : ils viennent d’un secret partagé et de l’heure, selon un algorithme public (RFC 6238).

Les ingrédients

Lors de l’inscription, le serveur génère un secret aléatoire et le transmet à l’application d’authentification, le plus souvent sous forme de QR code contenant une adresse otpauth:// avec le secret encodé en Base32. Ensuite, les deux côtés calculent le même code à partir de ce secret et de l’heure, sans rien échanger.

L’algorithme

  • On calcule un compteur : le timestamp Unix divisé par 30 (le time step), arrondi à l’entier inférieur.
  • On applique HMAC-SHA1 au compteur, écrit sur 8 octets, avec le secret comme clé.
  • Dynamic truncation : les quatre derniers bits du résultat donnent un offset, on lit 4 octets à partir de là et on masque le bit de poids fort.
  • On garde les six derniers chiffres (modulo 106), complétés de zéros à gauche.
import hmac, hashlib, struct, time

def totp(secret: bytes, period=30, digits=6, t=None):
    counter = int((time.time() if t is None else t) // period)
    h = hmac.new(secret, struct.pack(">Q", counter), hashlib.sha1).digest()
    offset = h[-1] & 0x0F
    number = struct.unpack(">I", h[offset:offset + 4])[0] & 0x7FFFFFFF
    return str(number % 10 ** digits).zfill(digits)

Vérification avec les vecteurs de test de la RFC 6238 (secret ASCII 12345678901234567890, SHA-1, 8 chiffres) :

secret = b"12345678901234567890"
print(totp(secret, digits=8, t=59))          # 94287082
print(totp(secret, digits=8, t=1111111109))  # 07081804

Bien vérifier côté serveur

  • Accepter le time step précédent et le suivant pour tolérer un léger décalage d’horloge.
  • Refuser un code déjà utilisé, en mémorisant le dernier time step accepté.
  • Limiter les tentatives : six chiffres, cela ne fait qu’un million de possibilités.
  • Comparer en constant-time (hmac.compare_digest) et stocker le secret chiffré, par exemple avec AES-GCM.
  • Fournir des codes de secours (backup codes), stockés hashés comme des mots de passe.

Les limites

Un code TOTP peut être volé par phishing en temps réel : la victime le saisit sur un faux site qui le rejoue aussitôt. Les clés d’accès (WebAuthn, passkeys) résistent à cette attaque parce qu’elles sont liées au domaine du vrai site.

Voir aussi : la plateforme de documents, qui utilise le TOTP

Sources

Retour au blog