Générateur de hash SRI

Donnez-nous l’adresse d’un script ou d’une feuille de style et recevez la balise avec son attribut integrity, plus une vérification que le navigateur l’acceptera. Vous pouvez aussi calculer le hash d’un fichier ou d’un code collé et cette partie reste sur votre appareil.

Une adresse https:// publique, jusqu’à 5 Mo. Le fichier est téléchargé par notre serveur, haché puis supprimé.

Ou essayez https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js, https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css

Ou calculez le hash d’un fichier sur votre appareil

Pour un fichier qui n’est pas encore en ligne, ou que vous préférez garder pour vous. Le hash est calculé par votre navigateur : ce que vous déposez ou collez ici ne nous est pas envoyé.

Choisissez un fichier, ou déposez-en un n’importe où dans cette zone.

Un sceau sur du code que vous n’hébergez pas

Quand votre page charge une bibliothèque depuis un CDN, vous donnez au serveur d’un inconnu le droit d’exécuter du code devant vos visiteurs. Si ce serveur est piraté, ou si le projet change de mains, la même adresse peut se mettre à renvoyer autre chose, comme un skimmer de cartes, un mineur de cryptomonnaie ou une redirection. Votre page continue de fonctionner sans que vous remarquiez rien. C’est arrivé à de vraies bibliothèques utilisées par des centaines de milliers de sites.

Subresource Integrity (SRI) est la fonction du navigateur qui répond à ce problème. Vous ajoutez à la balise une empreinte du fichier que vous avez examiné, calculée avec une fonction de hachage comme SHA-384. Le navigateur télécharge le fichier, recalcule l’empreinte, puis n’exécute le fichier que si les deux correspondent. Changez un seul octet et l’empreinte sort différente, donc le fichier est bloqué.

<script src="https://cdn.example.com/lib@2.4.1/lib.min.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Ce que cette page calcule et vérifie

Quand vous donnez une adresse, notre serveur télécharge le fichier une fois et envoie un en-tête Origin, comme le fait un navigateur pour une balise avec crossorigin. Le hash est calculé sur le corps après décodage gzip ou Brotli, ce qui correspond exactement à ce que hache un navigateur. Vous obtenez la balise complète avec SHA-384, ainsi que les valeurs SHA-256 et SHA-512.

Un hash correct ne garantit pas que la balise fonctionnera, alors nous lisons quatre autres éléments dans la réponse :

VérificationPourquoi c’est important
Access-Control-Allow-OriginPour un fichier venant d’une autre origine, le navigateur a besoin de cette permission avant d’avoir le droit de comparer les octets. Sans elle, une balise avec integrity échoue à tout coup. En-tête absent : erreur.
Version dans l’adresse/3.7.1/ ou @5.3.3 renvoie le même fichier pour toujours. @latest, @5, un nom de branche, une version seulement dans ?ver= ou aucune version signifie que le fichier peut changer et la page casse quand il change. Avertissement.
Cache-ControlUne durée d’un an ou immutable laisse penser que le fichier est figé. Une durée de moins d’un jour laisse penser que l’adresse est faite pour changer.
Content-TypeLes scripts doivent arriver en JavaScript et les feuilles de style en text/css. Les visionneuses de fichiers bruts envoient souvent text/plain, que les navigateurs refusent.

Une courte liste d’adresses est refusée d’emblée : chargeurs d’analytique et de gestionnaires de balises, scripts de paiement, feuilles de style de polices construites pour chaque navigateur. Leurs propriétaires les réécrivent sur place, donc y mettre un hash revient à programmer une panne.

La deuxième zone calcule le hash d’un fichier que vous déposez, ou d’un code que vous collez, avec le crypto.subtle du navigateur. Rien n’est téléversé.

Utiliser la balise sans casser votre page

  1. Fixez d’abord la version. Remplacez library@latest par la version exacte que vous avez testée, puis générez le hash pour cette adresse.
  2. Gardez crossorigin="anonymous". Sans cet attribut, le navigateur fait une requête qu’il n’a pas le droit d’inspecter et il bloque le fichier.
  3. Chargez la page et ouvrez la console. Une différence y apparaît comme un échec de la vérification d’intégrité, avec le nom du fichier.
  4. Mettez à jour volontairement. Une nouvelle version de la bibliothèque demande une nouvelle adresse et un nouveau hash. C’est un peu de travail et c’est aussi le but : rien ne change tant que vous ne l’avez pas décidé.

Pour les fichiers de votre propre domaine, SRI ne sert pas à grand-chose contre un attaquant qui contrôle déjà votre serveur, puisqu’il peut modifier la page et le hash ensemble. Il reste utile quand les pages et les ressources sont servies par des systèmes différents, par exemple le HTML par votre serveur et les fichiers par votre propre bucket CDN.

Limites : une requête depuis un seul endroit. Un serveur peut envoyer d’autres octets à un autre navigateur ou à une autre région et nous ne vérifions pas que le fichier est sûr, seulement qu’il est identique. Un attribut integrity couvre le fichier sur lequel il se trouve, pas les scripts que ce fichier charge ensuite.

Questions fréquentes

Quel hash utiliser : sha256, sha384 ou sha512 ?

Les navigateurs acceptent les trois et aucun n’est connu pour être faible. SHA-384 est la convention. C’est ce que publient les CDN et ce que montre la plupart de la documentation, alors utilisez-le sauf si une politique vous dit autre chose.

Pourquoi mon script ne se charge-t-il plus après l’ajout de integrity ?

Il y a trois causes habituelles. Le serveur n’envoie pas Access-Control-Allow-Origin, ou la balise n’a pas crossorigin="anonymous". Le fichier a changé depuis le calcul du hash, parce que l’adresse n’est pas liée à une version. Ou quelque chose entre le serveur et le navigateur réécrit le fichier, comme un proxy qui minifie les scripts. La console du navigateur vous dit laquelle.

Puis-je utiliser SRI avec Google Fonts, Google Analytics ou Stripe ?

Non. Ces adresses renvoient un contenu que leurs propriétaires mettent à jour quand ils veulent et la feuille de style des polices diffère d’un navigateur à l’autre. Un hash fixe les bloquerait au prochain changement. Limitez-les plutôt avec une Content-Security-Policy.

Le hash change-t-il si le serveur compresse le fichier ?

Non. Le navigateur vérifie le fichier après décompression, donc gzip, Brotli et zstd ne changent rien. Minifier ou reformater le fichier le modifie bel et bien.

Les images et les polices acceptent-elles l’attribut integrity ?

Pas aujourd’hui. Les navigateurs l’appliquent sur <script> et sur <link> pour les feuilles de style, les préchargements et les préchargements de modules. Sur les autres éléments, il est ignoré.

Comment calculer le même hash en ligne de commande ?

Avec OpenSSL : openssl dgst -sha384 -binary file.js | openssl base64 -A, puis placez sha384- devant le résultat.