Mode d’emploi
- Choisissez l’algorithme. HMAC-SHA256 est sélectionné par défaut : c’est celui qu’utilisent la plupart des webhooks et des API.
- Saisissez la clé secrète et réglez « Format de la clé » sur Texte (lu en UTF-8), Hexa ou Base64. Choisissez Hexa ou Base64 lorsque la clé est constituée d’octets bruts plutôt que d’une chaîne semblable à un mot de passe.
- Saisissez ou collez le message, passez l’entrée en Hexa pour des octets bruts, ou cliquez sur « Ouvrir un fichier ». Le HMAC se met à jour pendant la saisie.
- Dans « Format de sortie », choisissez « hexa (minuscules) », « HEXA (majuscules) » ou « Base64 » et copiez le résultat, ou collez une signature reçue dans « Comparer avec » pour obtenir « Correspondance » ou « Aucune correspondance ».
Fonctionnement du HMAC
HMAC (hash-based message authentication code, ou code d’authentification de message fondé sur le hachage, RFC 2104) associe une fonction de hachage cryptographique à une clé secrète. Seule une personne qui connaît la clé peut produire la bonne valeur pour un message : un HMAC correct prouve donc deux choses à la fois, à savoir que le message n’a pas été modifié et qu’il provient d’un détenteur de la clé.
La construction est H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)). La clé est d’abord hachée si elle dépasse la taille de bloc du hachage (64 octets pour MD5, SHA-1 et SHA-256, 128 pour SHA-384 et SHA-512), complétée par des zéros jusqu’à cette taille, puis combinée par XOR avec ipad (octets 0x36) pour un hachage interne portant sur le message, et avec opad (octets 0x5c) pour un hachage externe portant sur le résultat interne. Une construction naïve comme SHA-256(key ‖ message) n’a pas de hachage externe : quiconque voit une seule étiquette d’authentification peut ajouter des données au message et calculer une nouvelle étiquette valide sans la clé (attaque par extension de longueur).
La sortie a la longueur du hachage sous-jacent : 32 octets, soit 64 caractères hexadécimaux, pour HMAC-SHA256. La RFC 2104 recommande une clé au moins aussi longue, et le générateur de Base64 aléatoire en produit de convenables.
Utilisations des signatures HMAC
- Webhooks GitHub. L’en-tête
X-Hub-Signature-256contientsha256=suivi du HMAC-SHA256 hexadécimal du corps brut de la requête, calculé avec le secret du webhook comme clé. Vous pouvez coller la valeur complète de l’en-tête dans « Comparer avec » : le préfixesha256=est ignoré. - Webhooks Stripe. L’en-tête
Stripe-Signaturecontient un horodatagetet une signaturev1: le HMAC-SHA256 hexadécimal de l’horodatage, d’un point et du corps brut, calculé avec le secret du point de terminaison (whsec_...) utilisé comme texte. - Webhooks Shopify.
X-Shopify-Hmac-Sha256contient le HMAC-SHA256 du corps brut en Base64, calculé avec le secret client de l’application comme clé : choisissez donc la sortie Base64 ou collez la valeur de l’en-tête dans « Comparer avec ». - AWS Signature Version 4. La clé de signature est dérivée en enchaînant des HMAC-SHA256 : la date, avec pour clé
AWS4suivi de la clé d’accès secrète, puis la région, le service etaws4_request, chacun avec pour clé le résultat précédent. Réglez le format de la clé sur Hexa pour réinjecter la sortie d’une étape dans la suivante. - JSON Web Tokens. HS256, HS384 et HS512 sont des HMAC-SHA256, -384 et -512 calculés sur l’en-tête encodé, un point et la charge utile encodée. La troisième partie du jeton est ce HMAC en Base64 compatible URL, que « Comparer avec » accepte tel quel. Le décodeur JWT vérifie des jetons complets.
Calculez toujours le HMAC sur le corps brut, exactement tel qu’il a été reçu. Analyser le JSON puis le sérialiser à nouveau modifie les espaces ou l’ordre des clés, et un seul saut de ligne en trop donne un HMAC complètement différent.
Calculer un HMAC dans votre code
# Python
import hmac, hashlib
sig = hmac.new(b'key', b'message', hashlib.sha256).hexdigest()
hmac.compare_digest(sig, received) # comparaison en temps constant
// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', 'key').update('message').digest('hex');
// timingSafeEqual lève une exception si les longueurs diffèrent : vérifiez-les d’abord
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(received));
// PHP : le message se place avant la clé
$sig = hash_hmac('sha256', 'message', 'key');
hash_equals($sig, $received);
# OpenSSL : une clé texte, puis la même clé donnée en hexadécimal
printf '%s' 'message' | openssl dgst -sha256 -hmac 'key'
printf '%s' 'message' | openssl dgst -sha256 -mac HMAC -macopt hexkey:6b6579
# Vecteur de test : clé "key", message "The quick brown fox jumps over the lazy dog"
# HMAC-SHA256 = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
Lorsque vous vérifiez une signature dans votre propre code, utilisez une comparaison en temps constant comme celles ci-dessus. Un simple == s’arrête au premier caractère différent, et cet écart de durée peut permettre à un attaquant de trouver une signature valide octet par octet. Pour les schémas horodatés comme celui de Stripe, rejetez aussi les requêtes dont l’horodatage remonte à plus de quelques minutes, ce qui bloque les rejeux.
Questions fréquentes
HMAC-MD5 et HMAC-SHA1 sont-ils encore sûrs ?
Les attaques par collision cassent MD5 et SHA-1 en tant que simples fonctions de hachage, mais elles ne permettent pas en pratique de falsifier un HMAC, dont la sécurité repose sur d’autres propriétés du hachage et sur une clé secrète (la RFC 6151 traite le cas de HMAC-MD5). Les intégrations qui les exigent, comme les codes TOTP fondés sur HMAC-SHA1, peuvent être conservées. Pour toute nouvelle conception, utilisez HMAC-SHA256.
Pourquoi mon HMAC ne correspond-il pas à la signature du webhook ?
Les causes habituelles sont le hachage d’un JSON analysé puis resérialisé au lieu du corps brut, un saut de ligne final dans le message, un mauvais secret ou un mauvais format de clé (un secret Base64 ou hexadécimal saisi en Texte, ou l’inverse), et un mauvais algorithme. La différence entre hexa et Base64 ne pose en revanche aucun problème : « Comparer avec » accepte l’hexadécimal en minuscules comme en majuscules, le Base64 standard et le Base64 compatible URL.
Quelle est la différence entre un HMAC et un simple hachage ?
Un HMAC est-il la même chose qu’une signature numérique ?
Non. Les deux parties d’un HMAC partagent un même secret : quiconque peut vérifier une étiquette peut donc aussi en créer une. Les signatures comme RSA ou ECDSA (RS256 ou ES256 dans les JWT) sont produites avec une clé privée et vérifiées avec une clé publique : ceux qui les vérifient ne peuvent donc pas les falsifier.
Ma clé secrète est-elle envoyée à un serveur ?
Non. HMAC-SHA1 et les variantes SHA-2 sont calculés avec l’API Web Crypto de votre navigateur, et HMAC-MD5 par du JavaScript dans la page. La clé et le message ne quittent jamais votre appareil. Manipulez tout de même les secrets de production avec précaution et renouvelez une clé si elle a pu être exposée.