Como gerar um hash SRI
- O modo SRI já está selecionado. Em Hashes:, marque sha256, sha384 e/ou sha512; sha384 vem marcado por padrão.
- Arraste os arquivos
.jsou.csscom Entrada em Arquivo. O tipo de tag segue a extensão do arquivo. - Ou, com Entrada em Texto, cole o conteúdo do arquivo em Conteúdo do arquivo (colar), escolha a Tag (
<script>ou<link rel="stylesheet">) e informe o Caminho ou a URL de onde o arquivo será servido. - Copie o valor de
integrityou a Tag HTML inteira. Se você marcou vários algoritmos, eles aparecem separados por espaço em um único atributo.
Arrastar o arquivo é mais confiável do que colar. Uma caixa de texto do navegador converte quebras de linha CRLF em LF, e uma quebra de linha final ausente ou a mais muda o hash; a ferramenta lembra você das duas coisas.
O que é o valor de integrity
Um valor SRI é o nome do algoritmo, um hífen e o digest em Base64 dos bytes exatos do arquivo. Para um arquivo app.js com uma linha, console.log('hello');, seguida de uma quebra de linha:
<script src="https://cdn.example.com/app.js"
integrity="sha384-eEqgsNuDqSzbarn2kIY7c4WH6zkoJrjJRQIhlYgVwRR+6Eb8tkfTItTNLlIjbE3O"
crossorigin="anonymous"></script>
Sem a quebra de linha final, a mesma linha gera o hash sha384-v393mDht/MNBowq0Z9UpetDvKE6u6EdCihklP1GZs66vL1YCFm1Z4Q4wJtb94rY9. O navegador baixa o arquivo, calcula o hash do corpo recebido (depois de remover a compressão de transferência gzip ou Brotli, então a compressão não interfere) e se recusa a executá-lo ou aplicá-lo se nenhum hash listado bater.
Quando o SRI vale a pena
O SRI protege você quando outra pessoa serve o seu código: uma CDN pública, um host de widgets de terceiros, um bucket de armazenamento compartilhado com outras equipes. Se esse servidor for comprometido e o arquivo for trocado, os navegadores bloqueiam o arquivo modificado em vez de executá-lo nas suas páginas.
Ele serve para arquivos que nunca mudam em uma dada URL, como library@1.2.3/dist/lib.min.js. Não serve para:
- URLs como
/latest/ou@1, que passam a apontar para novas versões. - Respostas que variam por navegador ou região, como certos CSS de web fonts que entregam regras
@font-facediferentes conforme o user agent. - Scripts que o fornecedor atualiza no mesmo endereço de propósito, como muitos carregadores de analytics e de chat. Com eles, você precisa escolher entre o SRI e as atualizações do fornecedor.
Para os seus próprios arquivos no seu próprio domínio, o SRI acrescenta pouco: um atacante que consegue alterar o arquivo normalmente consegue alterar o HTML também. Ali, uma Content Security Policy é a ferramenta melhor; o gerador de nonce CSP e os hashes CSP de SHA-256 para Base64 cobrem esse lado.
CORS e o atributo crossorigin
Um arquivo de outra origem com atributo integrity precisa ser buscado em modo CORS, e o servidor precisa permitir isso com Access-Control-Allow-Origin (normalmente * em CDNs públicas). É isso que crossorigin="anonymous" solicita; a tag gerada sempre o inclui. Sem CORS, o navegador não consegue ler os bytes para calcular o hash e bloqueia o arquivo, com uma mensagem no console indicando a falha de integrity ou de CORS.
Arquivos da mesma origem não precisam do atributo, mas ele não atrapalha.
Gerando hashes SRI no build
Para mais do que alguns arquivos, calcule os hashes na etapa de build:
openssl dgst -sha384 -binary app.js | openssl base64 -A
const crypto = require("crypto");
const fs = require("fs");
const integrity = "sha384-" +
crypto.createHash("sha384").update(fs.readFileSync("app.js")).digest("base64");
console.log(integrity);
Os dois imprimem o valor eEqgsNuD… acima para o arquivo de exemplo. Os bundlers costumam ter um plugin que escreve o atributo no HTML para você, o que mantém os hashes em dia a cada build. Para conferir um valor que você recebeu, arraste o arquivo aqui e compare; a comparação é exata, caractere por caractere.
Perguntas frequentes
Qual algoritmo devo usar para SRI?
SHA-384 é a escolha usual e a que as CDNs costumam publicar. Os navegadores aceitam sha256, sha384 e sha512; quando vários são listados, usam o mais forte presente e ignoram os mais fracos.
Por que o navegador bloqueia meu script depois que adicionei integrity?
Ou os bytes são diferentes dos que você usou no hash, ou o arquivo vem de outra origem sem CORS. Leia a mensagem no console, compare com o arquivo que o servidor realmente entrega e confira se a resposta tem Access-Control-Allow-Origin e a tag tem crossorigin="anonymous".
Posso usar SRI com um arquivo que muda, como uma URL "latest"?
Não. O hash fixa uma versão exata, então qualquer atualização quebra a página até você atualizar o hash. Aponte para uma URL com versão, ou liste o hash antigo e o novo lado a lado enquanto distribui uma mudança.
Como gerar um hash SRI na linha de comando?
Rode openssl dgst -sha384 -binary app.js | openssl base64 -A e coloque sha384- na frente do resultado. Mantenha -binary: sem ela você codificaria o texto hex.