HMAC et les pièges

Pourquoi pas Hash(clé || message) : HMAC

L'idée la plus naïve pour fabriquer un MAC serait de coller la clé devant le message et de tout hacher :

tag = H(clé || message)     (|| = concaténation)

C'est séduisant, mais dangereux avec les fonctions de hachage les plus répandues.

L'attaque par extension de longueur

Les fonctions comme MD5, SHA-1 et SHA-256 sont bâties sur la construction dite de Merkle-Damgård : elles traitent le message par blocs, et l'empreinte finale est exactement l'état interne de la machine après le dernier bloc.

Conséquence : connaître H(clé || message) revient à connaître l'état interne à ce point. Un attaquant peut alors reprendre le calcul là où il s'est arrêté et ajouter des données de son choix, sans connaître la clé :

Il connaît :  tag  = H(clé || message)
Il calcule :  tag' = H(clé || message || padding || AJOUT)

  ... en repartant de l'état "tag", sans jamais voir la clé !

Il obtient un tag valide pour un message qu'il a allongé. La clé secrète ne l'a pas protégé. C'est l'attaque par extension de longueur (length extension attack).

La parade : HMAC

HMAC (Hash-based MAC) résout élégamment le problème en appliquant la fonction de hachage deux fois, avec deux dérivés de la clé :

HMAC(K, m) = H( (K XOR opad) || H( (K XOR ipad) || m ) )

ipad et opad sont deux constantes fixes (les octets 0x36 et 0x5c répétés).

                 message m
                    |
        K XOR ipad  |
              \     |
               v    v
        H( (K^ipad) || m )    <--- hachage interne
                    |
                    v   résultat intermédiaire
        K XOR opad  |
              \     |
               v    v
        H( (K^opad) || ... )  <--- hachage externe
                    |
                    v
                  HMAC

Pourquoi ça marche

Le hachage externe enveloppe le résultat interne. Un attaquant ne voit que la sortie de la couche externe ; il ne peut pas récupérer l'état interne exploitable pour prolonger le message. L'extension de longueur devient impossible.

HMAC a aussi l'avantage d'être prouvé sûr sous des hypothèses raisonnables sur la fonction de hachage, et de fonctionner avec n'importe laquelle (HMAC-SHA256, HMAC-SHA512...).

En résumé

La construction naïve H(clé || message) est vulnérable à l'attaque par extension de longueur sur les hachages de type Merkle-Damgård (MD5, SHA-1, SHA-256) : l'empreinte révèle l'état interne, ce qui permet de prolonger le message sans la clé. HMAC corrige cela par une double application du hachage — H((K XOR opad) || H((K XOR ipad) || m)) — dont la couche externe masque l'état interne. C'est la construction standard, sûre et indépendante de la fonction de hachage choisie.