Generador de hash SRI
Danos la dirección de un script o de una hoja de estilo y te devolvemos la etiqueta con su atributo integrity, más una comprobación de que el navegador la aceptará. También puedes calcular el hash de un archivo o de código pegado, y eso se queda en tu dispositivo.
O calcula el hash de un archivo en tu dispositivo
Para un archivo que todavía no está en línea, o que prefieres guardar para ti. El hash lo calcula tu navegador: lo que sueltes o pegues aquí no se nos envía.
Elige un archivo, o suelta uno en cualquier parte de este recuadro.
Un sello para código que no alojas tú
Cuando tu página carga una biblioteca desde un CDN, le das a un servidor ajeno el derecho de ejecutar código delante de tus visitantes. Si ese servidor sufre una intrusión, o el proyecto cambia de manos, la misma dirección puede empezar a devolver otra cosa, como un robatarjetas, un minero de criptomonedas o una redirección. Tu página sigue funcionando y no te enteras. Esto ha pasado con bibliotecas reales usadas por cientos de miles de sitios.
Subresource Integrity (SRI) es la función del navegador que se ocupa de esto. Añades a la etiqueta una huella del archivo que revisaste, calculada con una función hash como SHA-384. El navegador descarga el archivo, vuelve a calcular la huella y lo ejecuta solo si coinciden. Cambia un solo byte y la huella sale distinta, así que el archivo se bloquea.
<script src="https://cdn.example.com/lib@2.4.1/lib.min.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>Lo que calcula y comprueba esta página
Cuando das una dirección, nuestro servidor descarga el archivo una vez y envía una cabecera Origin, como hace un navegador con una etiqueta que lleva crossorigin. El hash se calcula sobre el cuerpo ya descomprimido de gzip o Brotli, que es exactamente lo que hashea un navegador. Recibes la etiqueta completa con SHA-384, y también los valores SHA-256 y SHA-512.
Un hash correcto no garantiza que la etiqueta funcione, así que leemos cuatro cosas más de la respuesta:
| Comprobación | Por qué importa |
|---|---|
Access-Control-Allow-Origin | Para un archivo de otro origen, el navegador necesita este permiso antes de poder comparar bytes. Sin él, una etiqueta con integrity falla siempre. Cabecera ausente: error. |
| Versión en la dirección | /3.7.1/ o @5.3.3 devuelven siempre el mismo archivo. @latest, @5, el nombre de una rama, una versión solo en ?ver= o ninguna versión significan que el archivo puede cambiar, y la página se rompe cuando cambia. Advertencia. |
Cache-Control | Una duración de un año o immutable sugiere un archivo congelado. Una duración de menos de un día sugiere que la dirección está pensada para cambiar. |
Content-Type | Los scripts tienen que llegar como JavaScript y las hojas de estilo como text/css. Los visores de archivos en bruto suelen enviar text/plain, que los navegadores rechazan. |
Una lista corta de direcciones se rechaza sin más: cargadores de analítica y de gestores de etiquetas, scripts de pago, hojas de estilo de fuentes generadas por navegador. Sus dueños las reescriben sobre la marcha, así que ponerles un hash es programar una caída.
El segundo cuadro calcula el hash de un archivo que sueltas, o de código que pegas, con el crypto.subtle del propio navegador. No se sube nada.
Usar la etiqueta sin romper tu página
- Fija primero la versión. Cambia
library@latestpor la versión exacta que probaste, y luego genera el hash de esa dirección. - Conserva
crossorigin="anonymous". Sin él, el navegador hace una solicitud que no puede inspeccionar y bloquea el archivo. - Carga la página y abre la consola. Una discrepancia aparece ahí como un fallo de comprobación de integridad, con el nombre del archivo.
- Actualiza a propósito. Una versión nueva de la biblioteca necesita una dirección nueva y un hash nuevo. Es un poco de trabajo, y ese es justo el objetivo: nada cambia hasta que tú lo decides.
Para archivos de tu propio dominio, SRI no sirve de mucho contra un atacante que ya controla tu servidor, porque puede editar la página y el hash a la vez. Sigue siendo útil cuando páginas y recursos se sirven desde sistemas distintos, por ejemplo el HTML desde tu servidor y los archivos desde tu propio bucket de CDN.
Límites: una solicitud desde un solo lugar. Un servidor puede enviar otros bytes a otro navegador o región, y no comprobamos que el archivo sea seguro, solo que sea el mismo. Un atributo integrity cubre el archivo en el que está, no los scripts que ese archivo cargue después.
Preguntas frecuentes
¿Qué hash debo usar: sha256, sha384 o sha512?
Los navegadores aceptan los tres y ninguno se conoce como débil. SHA-384 es la convención. Es el que publican los CDN y el que muestra la mayoría de la documentación, así que úsalo salvo que una política te diga otra cosa.
¿Por qué mi script deja de cargarse después de añadir integrity?
Hay tres causas habituales. El servidor no envía Access-Control-Allow-Origin, o a la etiqueta le falta crossorigin="anonymous". El archivo cambió desde que se calculó el hash, porque la dirección no está ligada a una versión. O algo entre el servidor y el navegador reescribe el archivo, como un proxy que minifica scripts. La consola del navegador te dice cuál es.
¿Puedo usar SRI con Google Fonts, Google Analytics o Stripe?
No. Esas direcciones devuelven contenido que sus dueños actualizan cuando quieren, y la hoja de estilo de las fuentes es distinta de un navegador a otro. Un hash fijo las bloquearía en el siguiente cambio. Restríngelas mejor con una Content-Security-Policy.
¿Cambia el hash si el servidor comprime el archivo?
No. El navegador comprueba el archivo después de descomprimirlo, así que gzip, Brotli y zstd no influyen. Minificar o reformatear el archivo sí lo cambia.
¿Las imágenes y las fuentes admiten el atributo integrity?
Hoy no. Los navegadores lo aplican en <script> y en <link> para hojas de estilo, precargas y precargas de módulos. En otros elementos se ignora.
¿Cómo calculo el mismo hash en la línea de comandos?
Con OpenSSL: openssl dgst -sha384 -binary file.js | openssl base64 -A, y luego pon sha384- delante del resultado.