Le guide complet du TOTP en équipe

Comment fonctionne TOTP, quelles propriétés de l’algorithme causent tous les problèmes de comptes partagés, et ce qu’une équipe doit mettre en place.

TOTP prend deux entrées et produit une sortie. Les entrées sont un secret partagé et l’heure courante ; la sortie est un code à six chiffres que quiconque détient le même secret peut calculer. Il n’y a aucun appel réseau, aucun enregistrement par appareil, et aucune trace côté serveur de l’appareil qui a produit un code.

Toutes les difficultés qu’une équipe rencontre avec la 2FA sur des comptes partagés découlent de cette phrase. Ce guide explique le mécanisme, puis ce qu’il implique pour une équipe de plus d’une personne.

Qu’est-ce que le TOTP ?

TOTP est spécifié par la RFC 6238. C’est une fine couche au-dessus de HOTP (RFC 4226), qui produit un code à partir d’un secret et d’un compteur. HOTP incrémente le compteur à chaque usage ; TOTP remplace le compteur par l’heure courante découpée en pas fixes, pour que les deux côtés arrivent à la même valeur sans communiquer.

Comment fonctionne le TOTP ?

Une génération ressemble à ceci :

counter = floor(unix_time / period)        # la période fait en général 30 secondes
digest  = hmac_sha1(secret, counter)       # 20 octets
offset  = digest[-1] & 0x0F                # troncature dynamique
number  = int_from(digest[offset:offset+4]) & 0x7FFFFFFF
code    = number % 10 ** digits            # complété de zéros, 6 chiffres en général

Quatre paramètres sont en jeu : le secret, la période (30 secondes par défaut), le nombre de chiffres (6) et l’algorithme (SHA-1 en pratique). L’application d’authentification d’un téléphone fait exactement ce qui précède, hors ligne. Le serveur fait la même chose et compare.

Deux conséquences méritent d’être dites clairement, parce que c’est là que commencent la plupart des malentendus :

  • Rien dans un code n’identifie sa source. Le serveur voit six chiffres qui correspondent, pas quel appareil ni quelle personne les a produits.
  • Il n’y a aucun état à révoquer. Enrôler un appareil n’est pas un enregistrement, c’est une copie du secret. Rien dans le compte n’en garde trace.

Le secret, c’est le compte

Le secret fait en général 16 à 32 caractères base32. Il n’expire pas, il n’est lié à aucun appareil, et le protocole n’a aucune notion de sa rotation.

Quand vous scannez un QR code de configuration, vous lisez une URI au format publié sous le nom de Key URI Format :

otpauth://totp/Acme:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Acme&algorithm=SHA1&digits=6&period=30

Cette chaîne est l’identifiant tout entier. Le QR code en est une photo. Ce qui veut dire qu’une capture de l’écran d’enrôlement n’est pas une commodité. C’est le second facteur, sous une forme qui se transfère, se sauvegarde et s’indexe.

De là découlent les propriétés qui rendent la 2FA partagée inconfortable :

  1. La possession vaut accès permanent. Qui a le secret peut produire tous les codes à venir, sur n’importe quel appareil, pour toujours.
  2. Les copies sont invisibles. Aucune page de sécurité ne vous dira jamais combien il en existe.
  3. Révoquer veut dire tout reprendre. Le seul moyen d’invalider une copie est de désactiver la 2FA sur le compte et de la reconfigurer, pour tout le monde.

L’enrôlement, étape par étape

Ce qui se passe pendant la configuration explique pourquoi certains choix ultérieurs sont irréversibles.

  1. Le fournisseur produit le secret. Il est créé côté serveur, enregistré sur votre compte, et ne change plus jamais à moins que la 2FA soit désactivée.
  2. Il est présenté une fois, sous forme de QR code et en général sous forme de chaîne base32 derrière un lien « impossible de scanner ? ». C’est le seul moment où l’identifiant est montré à un humain.
  3. Votre client le stocke. Une application d’authentification l’écrit sur l’appareil ; un coffre d’équipe l’écrit dans son propre stockage chiffré. Les deux font la même chose : garder une copie.
  4. Vous soumettez un code pour confirmer. Ça prouve que la copie fonctionne. Ce n’est pas un enregistrement de l’appareil : rien concernant votre téléphone n’est envoyé où que ce soit.
  5. Le fournisseur délivre des codes de récupération, en général à ce moment-là, et en général une seule fois.

L’étape 2 est tout l’enjeu. Ce qui voit cet écran détient le second facteur du compte à partir de là, et l’étape 4 ne donne aucune indication sur le nombre de choses qui l’ont vu. C’est pour ça que « on va juste en faire une capture pour l’instant » est une décision sans date d’expiration, et pourquoi la bonne question pendant la configuration n’est pas qui le scanne, mais où l’unique copie va vivre.

Pourquoi la fenêtre de trente secondes existe

Les deux côtés doivent s’accorder sur le compteur sans se parler : ils s’accordent donc sur l’heure. Un pas de trente secondes est le compromis : assez long pour taper un code, assez court pour qu’un code capturé ne vaille plus rien peu après.

Les vérificateurs acceptent en général aussi le pas immédiatement précédent, et parfois le suivant, pour absorber le temps de saisie et les petits écarts d’horloge. C’est pour ça qu’un code marche souvent encore quelques secondes après la remise à zéro du décompte.

Ça veut dire aussi que les horloges comptent. Un appareil dont l’horloge a une minute de décalage calcule les codes d’un pas que le serveur a déjà quitté, et tous les codes sont rejetés. Quand quelqu’un signale que les codes ont cessé de fonctionner, une horloge non synchronisée est la première chose à vérifier, avant de supposer que le secret est faux. Tout ce qui produit des codes pour une équipe a besoin d’une horloge synchronisée comme d’une exigence stricte, pas d’un confort.

Comment la vérification fonctionne, et pourquoi un code ne devrait servir qu’une fois

De l’autre côté, le vérificateur calcule le code attendu pour le pas courant et compare. Trois détails de cette comparaison comptent pour qui gère des comptes partagés.

La fenêtre d’acceptation est un arbitrage délibéré. Chaque pas supplémentaire accepté par un serveur allonge la durée pendant laquelle un code capturé reste utilisable. Un pas en arrière est normal ; de larges fenêtres signalent un service qui masque des problèmes d’horloge.

Un code devrait être à usage unique. La RFC 6238 dit explicitement qu’une seconde authentification avec le même pas de temps devrait être refusée, et les bonnes implémentations suivent le dernier pas utilisé par compte. L’effet pratique pour une équipe : deux personnes qui se connectent dans les mêmes trente secondes peuvent voir la seconde tentative rejetée alors même que le code affiché est correct. Attendre le code suivant est le remède, et ce n’est pas un bug.

Les tentatives devraient être limitées. Six chiffres, c’est un million de possibilités, ce qui ne résiste à la force brute que si le serveur limite les essais. Cette protection vit entièrement côté fournisseur ; rien de ce que vous faites du secret ne l’améliore.

Aucun de ces points ne se configure du côté d’une équipe, mais tous les trois expliquent des symptômes qui, sinon, ressemblent à une configuration cassée : un code qui marche en retard, un code qui marche pour un collègue et pas pour le suivant, une connexion qui se met à refuser des codes corrects après une rafale de tentatives.

Le TOTP est-il sûr ? Ce contre quoi il protège, et ce contre quoi il ne protège pas

Il défend bien contre les mots de passe réutilisés, le bourrage d’identifiants issus de fuites, et un mot de passe fuité isolément. Un attaquant qui n’a que le mot de passe ne peut pas se connecter.

Il ne défend pas contre un relais en temps réel : une fausse page de connexion convaincante qui demande le code et le transmet dans sa fenêtre de validité. Les codes TOTP sont hameçonnables par conception, puisque l’utilisateur peut les lire. Il ne fait rien non plus contre un logiciel malveillant sur l’appareil qui les produit, un cookie de session volé, ou un secret copié.

Ce dernier point est la faille qui concerne les équipes. Toutes les autres menaces de la liste sont traitées par les réglages de sécurité du compte lui-même. Un secret copié n’est traité que par la façon dont votre équipe en assure la garde, ce que le fournisseur ne peut ni voir ni aider.

Là où les équipes cassent TOTP

Par dégâts croissants :

  • Une personne garde l’application. Aucun secret n’est copié, mais le compte dépend désormais de la disponibilité d’un être humain.
  • Un téléphone dédié dans un tiroir. Très bien au bureau, inutile à distance, et ça n’enregistre rien.
  • Le secret à côté du mot de passe dans un coffre partagé. Pratique, et ça réunit les deux facteurs dans un seul contenant.
  • Le QR code publié dans un canal. Distribution permanente et incomptable de l’identifiant.

Les arbitrages de chacun, et la façon de choisir, font le sujet de les meilleures façons de gérer la 2FA d’un compte partagé et, type de compte par type de compte, de la 2FA d’un compte partagé : comment une équipe devrait-elle s’y prendre ?.

Ce qu’exige une installation TOTP taillée pour une équipe

Une installation qui survit à plus d’une personne a besoin de six choses, quel que soit l’outil retenu. C’est la liste à vérifier avant de choisir.

Une garde unique du secret. Un seul endroit le détient, saisi une fois, par la personne qui administre le compte. Tout le reste consomme des codes.

Une distribution des codes sans distribution du secret. Ceux qui doivent se connecter obtiennent le code courant et le décompte, et ne peuvent pas reconstituer le secret à partir de ce qu’ils voient.

Une autorisation par personne et par compte. Pas par coffre. Celui qui publie sur le profil social n’a aucune raison de produire des codes pour le prestataire de paiement.

Une trace des consultations de codes. Le journal du fournisseur montrera le compte partagé, pas la personne. Un registre de qui a demandé un code est la seule chose qui ramène un incident à un nom et un horodatage.

Une horloge synchronisée partout où des codes sont produits, pour la raison donnée plus haut.

Un chemin de récupération testé. C’est la partie que les équipes découvrent au pire moment.

Sauvegardes et récupération

Deux choses distinctes doivent être récupérables, et elles ne devraient vivre ni au même endroit l’une que l’autre, ni dans le compte qu’elles protègent.

Le secret, parce que le perdre oblige à réinitialiser la 2FA du compte. Son emplacement devrait être noté, et atteignable par plus d’un administrateur.

Les codes de récupération du fournisseur, qui sont des replis à usage unique délivrés à l’enrôlement. Ils servent au jour où le secret a disparu, pas à l’accès quotidien : ils sont en nombre fini, et personne ne peut dire lequel a été consommé par qui.

Ranger l’unique copie d’un code de récupération dans le compte qu’il récupère est une boucle qui se referme exactement quand vous en avez besoin ouverte. Idem pour le secret du compte qui garde le coffre qui contient vos secrets.

Le chemin de récupération mérite d’être parcouru une fois, délibérément, sur un compte sans enjeu : désactiver la 2FA avec un code de récupération, la reconfigurer, vérifier que tous ceux qui ont besoin des codes les ont toujours. Sans ce passage à blanc, vous découvrirez la procédure le jour où le compte est déjà inaccessible.

Les paramètres que vous rencontrerez vraiment

Les valeurs par défaut couvrent l’écrasante majorité : SHA-1, six chiffres, trente secondes. L’usage de SHA-1 ici n’est pas la faiblesse qu’il semble être, puisque HMAC-SHA1 n’est pas affecté par les attaques par collision qui ont mis SHA-1 à la retraite pour les signatures. La RFC autorise SHA-256 et SHA-512, mais la prise en charge par les applications est assez inégale pour que les fournisseurs s’en servent rarement.

Une minorité de services s’écartent : huit chiffres, une période de soixante secondes, ou un alphabet de code non numérique. La conséquence pratique est une exigence de stockage. Ce qui détient un secret doit détenir ses paramètres digits, period et algorithm à côté, sans quoi les codes de ces comptes seront faux d’une manière qui ressemble à un secret cassé. Tout outil qui n’accepte qu’une chaîne de secret nue suppose en silence les valeurs par défaut.

Petit glossaire

Il vaut la peine de s’entendre dessus au sein d’une équipe, parce que ces mots sont employés indifféremment et que les gens finissent par parler de choses différentes.

  • Secret (ou graine) : la chaîne base32 dont viennent les codes. Permanente.
  • Clé : le plus souvent un synonyme de secret. Parfois on désigne par là le Key URI, qui est autre chose.
  • Code (ou OTP) : les six chiffres. Valable un pas, à usage unique.
  • Jeton (token) : employé indifféremment pour les six chiffres et, sur un matériel dédié, pour l’appareil qui détient le secret. Préciser lequel.
  • HOTP : la même construction avec un compteur qui s’incrémente à chaque usage.
  • Période / pas de temps : l’intervalle de validité d’un code, en général 30 secondes.
  • Dérive : l’écart entre deux horloges, qui fait échouer les codes.
  • Key URI / URI otpauth : la forme textuelle de la charge d’enrôlement ; le QR code en est l’encodage visuel.
  • Codes de récupération : des replis à usage unique fournis par le service, sans rapport avec TOTP.
  • Enrôlement : la copie du secret sur un appareil. Pas un enregistrement, malgré l’impression que ça donne.

Où Share Auth se place

Share Auth met en œuvre les six exigences ci-dessus pour les comptes qui n’ont vraiment qu’un identifiant. Les secrets sont saisis une fois et chiffrés au repos, avec digits, period et algorithm stockés à côté ; les membres voient des codes et des décomptes plutôt que des secrets ; les permissions sont par membre ; et chaque consultation est écrite dans un journal d’accès. Retirer un membre retire son accès à tous les comptes d’un coup.

Ce n’est pas un substitut à l’accès par personne sur les plateformes qui le proposent. Là où un outil peut donner à chaque coéquipier son propre identifiant et son propre second facteur, c’est strictement mieux que de partager quoi que ce soit.

Liste de contrôle

  • Le secret de chaque compte partagé a un domicile connu, atteignable par deux administrateurs.
  • Personne n’a besoin du secret pour obtenir un code.
  • L’accès est accordé par personne, par compte, et retirable en une action.
  • Les consultations de codes sont journalisées au moment où elles ont lieu.
  • Les codes de récupération sont rangés avec le secret, hors du compte qu’ils récupèrent.
  • Les horloges sont synchronisées partout où des codes sont produits.
  • Le chemin de récupération a été testé une fois, exprès.
  • Tout compte dont le QR code a été partagé un jour a vu sa 2FA réinitialisée.

Questions fréquentes

TOTP, pour « time-based one-time password », est l’algorithme spécifié par la RFC 6238 qui transforme un secret partagé et l’heure courante en un code court, six chiffres le plus souvent, valable une trentaine de secondes. Le compte et l’application d’authentification détiennent le même secret : ils calculent donc le même code sans rien échanger.

À lire aussi · Comment fonctionne TOTP