Prenez un secret partagé et l’heure courante divisée par trente. Calculez un HMAC-SHA1 de ce compteur avec ce secret. Prenez quatre octets à une position que le dernier octet désigne, gardez les trente et un bits de poids faible, et lisez les six derniers chiffres en décimal. Voilà toute la RFC 6238.
Toutes les questions que vous vous poserez sur TOTP découlent de cette description.
Pourquoi la dérive d’horloge compte, et combien en tolérer
Le compteur vient de l’horloge. Si le téléphone de l’utilisateur a quarante secondes d’écart, il calcule le code d’une autre fenêtre et rien ne correspond. Les serveurs acceptent donc une fenêtre de chaque côté.
Un pas de chaque côté, soit quatre-vingt-dix secondes en tout, est le compromis courant. Plus large est plus aimable et donne à un attaquant davantage de codes valables à chaque instant. C’est un choix, alors faites-le sciemment plutôt qu’en copiant un extrait.
Six chiffres n’est pas le paramètre de sécurité
Six chiffres donnent un million de possibilités, et un code valable vit trente secondes. Cela semble faible, et ce le serait, sans la seule chose qui fait que cela fonctionne : la limitation du nombre de tentatives.
La solidité de TOTP ne vient pas de la longueur du code. Elle vient du peu de tentatives que vous autorisez. Sans limite, un million d’essais contre un serveur au repos n’est pas un obstacle sérieux. Avec cinq tentatives, les mêmes six chiffres suffisent parfaitement.
Le rejeu, la moitié oubliée
Un code reste valable toute sa fenêtre. Si quelqu’un le lit par-dessus l’épaule de l’utilisateur, ou s’il apparaît dans une conversation d’assistance, il peut resservir dans la même fenêtre. Consignez le dernier compteur accepté par utilisateur et refusez-le une seconde fois. Cela coûte une colonne.
Le secret est tout l’enjeu
Le secret partagé est symétrique : quiconque détient votre base peut engendrer des codes valables pour chaque utilisateur, indéfiniment. Chiffrez cette colonne, gardez la clé ailleurs, et traitez une fuite comme une compromission complète du second facteur.
OTPHP implémente HOTP et TOTP, avec l’URI de provisionnement que les applications d’authentification lisent depuis un code QR.