Generatore di hash SRI

Dacci l’indirizzo di uno script o di un foglio di stile e ricevi il tag con il suo attributo integrity, più un controllo che il browser lo accetterà. Puoi anche calcolare l’hash di un file o di codice incollato, e quella parte resta sul tuo dispositivo.

Un indirizzo pubblico https://, fino a 5 MB. Il file viene scaricato dal nostro server, se ne calcola l’hash e poi viene eliminato.

Oppure prova 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

Oppure calcola l’hash di un file sul tuo dispositivo

Per un file che non è ancora online, o che preferisci tenere per te. L’hash è calcolato dal tuo browser: ciò che trascini o incolli qui non ci viene inviato.

Scegli un file, o trascinalo in un punto qualsiasi di questo riquadro.

Un sigillo sul codice che non ospiti tu

Quando la tua pagina carica una libreria da una CDN, stai dando al server di uno sconosciuto il diritto di eseguire codice davanti ai tuoi visitatori. Se quel server viene violato, o il progetto cambia proprietario, lo stesso indirizzo può cominciare a restituire altro: uno skimmer di carte, un miner di criptovalute, un redirect. La tua pagina continua a funzionare e tu non te ne accorgi. È successo davvero a librerie usate da centinaia di migliaia di siti.

Subresource Integrity (SRI) è la funzione del browser che risolve questo problema. Aggiungi al tag un’impronta del file che hai verificato, calcolata con una funzione di hash come SHA-384. Il browser scarica il file, ricalcola l’impronta ed esegue il file solo se le due coincidono. Basta cambiare un solo byte e l’impronta risulta diversa, quindi il file viene bloccato.

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

Cosa calcola e controlla questa pagina

Quando inserisci un indirizzo, il nostro server scarica il file una volta e invia un header Origin, come fa un browser per un tag con crossorigin. L’hash viene calcolato sul corpo dopo la decodifica gzip o Brotli, che è esattamente ciò di cui il browser calcola l’hash. Ottieni il tag completo con SHA-384, e anche i valori SHA-256 e SHA-512.

Un hash corretto non garantisce che il tag funzioni, quindi leggiamo altre quattro cose dalla risposta:

ControlloPerché conta
Access-Control-Allow-OriginPer un file di un’altra origine, il browser ha bisogno di questo permesso prima di poter confrontare i byte. Senza, un tag con integrity fallisce ogni volta. Header assente: errore.
Versione nell’indirizzo/3.7.1/ o @5.3.3 restituisce per sempre lo stesso file. @latest, @5, il nome di un branch, una versione solo in ?ver= o nessuna versione significano che il file può cambiare, e quando cambia la pagina si rompe. Avviso.
Cache-ControlUna durata di un anno o immutable fa pensare a un file congelato. Una durata inferiore a un giorno fa pensare a un indirizzo destinato a cambiare.
Content-TypeGli script devono arrivare come JavaScript e i fogli di stile come text/css. I visualizzatori di file grezzi spesso inviano text/plain, che i browser rifiutano.

Un breve elenco di indirizzi viene rifiutato subito: loader di analytics e tag manager, script di pagamento, fogli di stile dei font generati per ogni browser. I proprietari li riscrivono sul posto, quindi metterci un hash è un modo di programmare un guasto.

Il secondo riquadro calcola l’hash di un file che trascini, o di codice che incolli, con il crypto.subtle del browser stesso. Non viene caricato nulla.

Usare il tag senza rompere la pagina

  1. Prima fissa la versione. Cambia library@latest nella release esatta che hai provato, poi genera l’hash per quell’indirizzo.
  2. Tieni crossorigin="anonymous". Senza, il browser fa una richiesta che non ha il permesso di ispezionare e blocca il file.
  3. Carica la pagina e apri la console. Una mancata corrispondenza compare lì come controllo di integrità fallito, con il nome del file.
  4. Aggiorna di proposito. Una nuova versione della libreria richiede un nuovo indirizzo e un nuovo hash. È un po’ di lavoro, ma è anche lo scopo: niente cambia finché non lo decidi tu.

Per i file sul tuo stesso dominio, SRI serve a poco contro un attaccante che controlla già il tuo server, perché può modificare insieme la pagina e l’hash. Resta utile quando pagine e risorse sono servite da sistemi diversi, per esempio l’HTML dal tuo server e i file dal tuo bucket CDN.

Limiti: una richiesta da un solo punto. Un server può inviare byte diversi a un altro browser o a un’altra regione, e noi non controlliamo che il file sia sicuro, solo che sia lo stesso. Un attributo integrity copre il file su cui si trova, non gli script che quel file carica dopo.

Domande frequenti

Quale hash usare: sha256, sha384 o sha512?

I browser accettano tutti e tre e nessuno è considerato debole. SHA-384 è la convenzione. È quello che pubblicano le CDN e che mostra la maggior parte della documentazione, quindi usalo a meno che una policy non ti dica altrimenti.

Perché il mio script non si carica più dopo aver aggiunto integrity?

Le cause solite sono tre. Il server non invia Access-Control-Allow-Origin, oppure al tag manca crossorigin="anonymous". Il file è cambiato da quando è stato calcolato l’hash, perché l’indirizzo non è legato a una versione. Oppure qualcosa tra il server e il browser riscrive il file, come un proxy che minifica gli script. La console del browser ti dice quale.

Posso usare SRI con Google Fonts, Google Analytics o Stripe?

No. Quegli indirizzi restituiscono contenuti che i proprietari aggiornano quando vogliono, e il foglio di stile dei font cambia da un browser all’altro. Un hash fisso li bloccherebbe al cambiamento successivo. Limitali invece con una Content-Security-Policy.

L’hash cambia se il server comprime il file?

No. Il browser controlla il file dopo la decompressione, quindi gzip, Brotli e zstd non fanno differenza. Minificare o riformattare il file invece lo cambia.

Immagini e font supportano l’attributo integrity?

Oggi no. I browser lo applicano a <script> e a <link> per fogli di stile, preload e module preload. Sugli altri elementi viene ignorato.

Come calcolo lo stesso hash da riga di comando?

Con OpenSSL: openssl dgst -sha384 -binary file.js | openssl base64 -A, poi metti sha384- davanti al risultato.