Si vous activez 2FA pour Google Apps, le secret partagé est de 160 bits. Le google_authenticator
Le module PAM d'autre part semble utiliser 80 bits pour le secret partagé.
Selon RFC 4226 :
R6 - L'algorithme DOIT utiliser un secret partagé fort. La longueur de
le secret partagé DOIT être d'au moins 128 bits. Ce document
RECOMMANDE une longueur secrète partagée de 160 bits.
Notez "DOIT" et non "DEVRAIT". Cela rend donc Google Authenticator non conforme.
Quelle est la raison derrière cela?
commit initial pour ce code inclut déjà la longueur de clé secrète "80 bits". Cela n'a pas été changé par la suite.
Analysons maintenant les choses de manière plus critique. HOTP est spécifié dans RFC 4226 . L'authentification utilise un "secret partagé", qui est la valeur dont nous parlons. Que dit RFC 4226 à ce sujet? Essentiellement, il y a une exigence dans section 4 :
R6 - The algorithm MUST use a strong shared secret. The length of the shared secret MUST be at least 128 bits. This document RECOMMENDs a shared secret length of 160 bits.
Et puis section 7.5 explique en détail diverses méthodes pour générer le secret partagé.
Maintenant le google_authenticator
le code génère un secret partagé de 80 bits avec /dev/urandom
puis passe à encoder ce secret avec Base32 : cet encodage mappe chaque groupe de 5 bits à un caractère imprimable. La chaîne résultante se compose donc de 16 caractères, qui sont écrits "tels quels" dans un fichier, avec ASCII, ce qui signifie que dans le fichier le secret partagé a une longueur ... 16 octets, soit 128 bits. C'est donc possible que la confusion initiale vient de cela: ce qui est stocké a une longueur qui peut être vue, en quelque sorte, pour se conformer à l'exigence R6 de la RFC 4226.
Bien sûr, le RFC parle du "secret partagé" en l'appelant " [~ # ~] k [~ # ~]" dans section 5.1 puis continue à l'utiliser comme clé pour HMAC ( section 5. , étape 1). Avec le secret partagé généré avec l'outil de ligne de commande dans google_authenticator
, ce qui entre dans HMAC est vraiment une séquence de 80 bits, pas 128 bits, même si ces 80 bits se trouvent être encodés comme 128 bits lorsqu'ils sont stockés (mais ils sont décodés à 80 bits à l'utilisation). Ainsi, ce secret de 80 bits ne peut pas vraiment, d'une manière légaliste, se conformer à l'exigence R6 de la RFC 4226. Cependant, la confusion sur la "longueur" (après ou avant l'encodage) peut expliquer cette caractéristique de google_authenticator
.
Notez, cependant, que c'est uniquement pour l'outil de ligne de commande qui peut être utilisé pour générer le secret comme étape initiale. Le reste du code prend en charge des valeurs secrètes plus longues.
(Une autre théorie est que l'auteur voulait tester son code, et, en particulier, tester la situation dans laquelle il n'y a pas de code QR. Dans ce cas, l'utilisateur doit taper le code, et un secret 80 bits est plus facile à taper qu'un secret 128 bits ou 160 bits. Peut-être, l'auteur a d'abord utilisé un court secret pour faciliter le développement, puis a oublié de le remettre à sa longueur nominale par la suite. Ce genre d'incident se produit assez souvent.)
Est-ce critique? Avec mon chapeau de cryptographe, je dois répondre: non. Une clé secrète de 80 bits est encore assez forte contre la force brute, car même avec beaucoup de GPU, 279 les évaluations de HMAC/SHA-1 prendront encore un certain temps (avec une clé de 80 bits, le coût moyen de la force brute est celui d'essayer la moitié des clés possibles, c'est-à-dire 279 évaluations). En effet, HMAC/SHA-1 est considéré comme "cryptographiquement fort", ce qui signifie que l'attaque la plus connue est la force brute sur la clé. Mettons des chiffres dessus:
HMAC/SHA-1 utilise deux appels SHA-1. Ainsi, le coût d'attaque est, en moyenne, le coût impliqué en appelant SHA-1 280 fois. Cette page montre des références à 2,5 milliards d'appels SHA-1 par seconde pour un bon GPU. Si vous montez une ferme de craquage, vous utiliserez généralement un GPU "milieu de gamme", pas un modèle haut de gamme, car vous obtiendrez ainsi plus de puissance par dollar. Supposons que vous utilisez un GPU de 100 $ qui peut faire 231 SHA-1 par seconde (c'est un peu plus de 2 milliards). Avec un budget de un milliard de dollars vous pouvez avoir dix millions de ces GPU, et ils exécuteront l'attaque en moyenne ... 652 jours.
Bien sûr, 10 millions de GPU prennent assez de place et, plus important encore, consomment beaucoup d'énergie. Si nous supposons que chaque GPU peut fonctionner en 50W (un chiffre assez optimiste), chaque exécution d'attaque aura besoin d'un peu moins de 8 TW.h (térawatt-heures). J'habite au Canada, province de Québec, où l'électricité est connue pour être très bon marché en raison des énormes barrages et des subventions gouvernementales importantes, ce qui entraîne un prix d'environ 0,05 $ par kW.h (voir les prix ) . Avec ce prix, chaque course d'attaque coûtera environ 400 millions de dollars rien que pour l'électricité. Cela n'inclut pas les prix du refroidissement, car toute cette énergie deviendra de la chaleur et devra être dissipée (dans une certaine mesure, un hiver canadien peut aider). Notez également que tous les GPU tireront collectivement 500 MW, une quantité non discrète (c'est environ la moitié d'une centrale nucléaire ...).
Ce que cela signifie est le suivant: dans la pratique, une clé de 80 bits est suffisamment forte . Je serais nerveux si une clé de 80 bits protégeait le code de lancement des missiles nucléaires; cependant, si la dissuasion stratégique était protégée par le 2FA de Google, je serais également très nerveux pour ... d'autres raisons.
Nous pouvons donc dire que si ce secret 80 bits n'est pas conforme et académique "un peu court", il est toujours assez fort et ne nécessite pas d'actions immédiates et drastiques. Ce serait cool si le code était corrigé; le monde n'arrêtera pas de tourner s'il ne l'est pas.
Comme je l'ai mentionné dans mon commentaire, j'ai déjà ouvert un problème sur le référentiel Google Authenticator. Cependant, il n'y a eu aucune réponse officielle des développeurs à ce sujet. Il semble que l'activité sur le référentiel soit plutôt stagnante.
Bien qu'il n'y ait probablement aucune bonne explication pour expliquer pourquoi Google a opté pour 80 bits au lieu des 160 bits recommandés selon le RFC, il existe une solution assez simple s'il s'agit d'un problème important.
Pour autant que je sache, la taille du secret est uniquement définie dans libpam/google-authenticator.c
à la ligne 39.
#define SECRET_BITS 80 // Must be divisible by eight
Changer la valeur de 80 à 160 fonctionne et ne casse rien pour autant que je sache. Cela peut être viable si vous voulez vraiment que le module PAM soit conforme à la RFC.