← blog
JavaScript Web Crypto API Zero dipendenze Audit trail

Hash SHA-256 di un PDF con Web Crypto API, client-side

Come calcolare l'hash SHA-256 di un file PDF direttamente nel browser con crypto.subtle.digest — per audit trail e verifica integrità documenti, senza librerie esterne.

Il problema

In un sistema di conferma presa visione documenti, serve dimostrare che il PDF firmato sia esattamente lo stesso mostrato all'utente — senza un backend dedicato per il calcolo dell'hash. La Web Crypto API lo permette interamente lato client.

Calcolo hash da Blob

hash-pdf.js
async function calcolaHashPdf(pdfBlob) {
  const arrayBuffer = await pdfBlob.arrayBuffer();
  const hashBuffer  = await crypto.subtle.digest('SHA-256', arrayBuffer);
  const hashArray   = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Scarica blob da Firebase Storage e calcola hash prima di mostrare il documento
const pdfRef = storageRef(storage, item.pdfPath);
const url    = await getDownloadURL(pdfRef);
const res    = await fetch(url);
const blob   = await res.blob();
const hash   = await calcolaHashPdf(blob);

Quando usarlo: audit trail di documenti (presa visione, firme elettroniche semplici), verifica che un file scaricato non sia stato alterato, fingerprint univoco di file caricati dall'utente prima del salvataggio.

Il problema CORS di Firebase Storage

Il primo tentativo di scaricare il PDF con fetch(downloadURL) spesso fallisce silenziosamente — nessun errore visibile in console, ma il blob resta vuoto. Il motivo: Firebase Storage non configura automaticamente le policy CORS per richieste fetch() da origini esterne, e il browser blocca la risposta prima che JavaScript possa vederla.

cors.json — configurazione CORS bucket
[
  {
    "origin": ["https://tuodominio.it"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]
shell — applicazione con gsutil
# Richiede Google Cloud SDK installato
gsutil cors set cors.json gs://TUO-BUCKET.appspot.com

# Verifica configurazione applicata
gsutil cors get gs://TUO-BUCKET.appspot.com

Attenzione: la configurazione CORS è lato bucket, non richiede modifiche al codice — ma va applicata una sola volta tramite gsutil, non esiste un pannello equivalente nella Firebase Console.

Articolo correlato
Firma elettronica con OTP su Firebase — audit trail, hash PDF e certificato con pdf-lib