La Crypto di JavaScript: panoramica completa e guida pratica

 

JavaScript mette a disposizione una libreria chiamata Crypto API, pensata per gestire in modo sicuro operazioni come:

  • generazione di numeri casuali
  • creazione di hash
  • cifratura e decifratura dei dati
  • gestione delle chiavi crittografiche

Questa libreria non ha nulla a che fare con le criptovalute.
Serve esclusivamente per proteggere le informazioni nelle applicazioni web.

L’obiettivo di questo articolo è:

  1. capire cos’è la Crypto API
  2. capire cos’è crypto.subtle
  3. vedere quali problemi risolve
  4. imparare a usarla con esempi semplici e concreti
🔗 Ti piace Techelopment? Dai un'occhiata al sito per tutti i dettagli!

1. Cos’è la Crypto API di JavaScript (panoramica)

La Crypto API è una libreria integrata nel browser (e in Node.js) accessibile tramite l’oggetto globale:

crypto

Questa libreria è divisa in due parti principali:

Parte A cosa serve
crypto.getRandomValues() Numeri casuali sicuri
crypto.subtle Tutte le operazioni crittografiche

📌 Questo è il punto chiave dell’articolo:
tutto ciò che riguarda la vera crittografia sta dentro crypto.subtle


2. Perché esiste crypto.subtle

La crittografia:

  • è complessa
  • usa matematica avanzata
  • deve essere estremamente sicura

Per questo JavaScript:

  • non espone algoritmi semplici
  • obbliga a usare un’API controllata
  • rende le operazioni asincrone

Il nome subtle indica che:

la crittografia è “sottile”, delicata, e va usata con attenzione


3. Cosa puoi fare con crypto.subtle

crypto.subtle è un oggetto che contiene diversi metodi.

Panoramica delle funzioni principali

Funzione Serve per
digest() Creare hash
generateKey() Creare chiavi
encrypt() Cifrare dati
decrypt() Decifrare dati
sign() Firmare dati
verify() Verificare firme

In questo articolo ci concentreremo su:

  • digest
  • generateKey
  • encrypt
  • decrypt

4. Prima di iniziare: testo e dati binari

La Crypto API non lavora con stringhe.
Lavora con byte.

Perché?

I computer capiscono solo numeri.

Convertire una stringa in byte

const encoder = new TextEncoder();
const dati = encoder.encode("Ciao mondo");

Convertire byte in stringa

const decoder = new TextDecoder();
const testo = decoder.decode(dati);

Questa conversione è necessaria in tutti gli esempi successivi.


5. crypto.subtle.digest: creare un hash

Cos’è un hash (in breve)

  • trasforma un testo in una stringa fissa
  • è irreversibile
  • è usato soprattutto per le password

Esempio pratico: hash SHA-256

async function creaHash(testo) {
  const encoder = new TextEncoder();
  const dati = encoder.encode(testo);

  const hashBuffer = await crypto.subtle.digest(
    "SHA-256",
    dati
  );

  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray
    .map(b => b.toString(16).padStart(2, "0"))
    .join("");
}

Uso

creaHash("password123").then(console.log);

6. crypto.subtle.generateKey: creare una chiave

Per cifrare e decifrare servono chiavi crittografiche.

Esempio: chiave AES

const chiave = await crypto.subtle.generateKey(
  {
    name: "AES-GCM",
    length: 256
  },
  true,
  ["encrypt", "decrypt"]
);

Cosa stiamo facendo

  • scegliamo l’algoritmo
  • definiamo la sicurezza
  • diciamo cosa può fare la chiave

7. crypto.subtle.encrypt: cifrare un messaggio

Cos’è la cifratura

  • nasconde il contenuto
  • può essere invertita
  • richiede una chiave

Esempio completo

const iv = crypto.getRandomValues(
  new Uint8Array(12)
);

const encoder = new TextEncoder();
const messaggio = encoder.encode("Messaggio segreto");

const cifrato = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv },
  chiave,
  messaggio
);

Il risultato è dato binario, non testo.

In questo codice iv è l’Initialization Vector (in italiano: vettore di inizializzazione). È un elemento fondamentale per la cifratura con AES-GCM.

Vediamolo passo per passo.

Cos’è iv

const iv = crypto.getRandomValues(
  new Uint8Array(12)
);
  • iv è un array di 12 byte (96 bit) generati in modo casuale
  • Viene usato una sola volta per ogni operazione di cifratura
  • Non è una chiave segreta

In AES-GCM, 12 byte è la lunghezza raccomandata e standard.

A cosa serve l’IV

L’IV serve a:

1️⃣ Rendere ogni cifratura diversa

Anche se:

  • il messaggio è lo stesso
  • la chiave è la stessa

con un IV diverso, il risultato cifrato sarà completamente diverso.

Senza IV (o con IV riutilizzato):

Messaggio segreto → sempre lo stesso cifrato ❌

Con IV casuale:

Messaggio segreto → cifrato A
Messaggio segreto → cifrato B

2️⃣ Garantire la sicurezza di AES-GCM

AES-GCM diventa insicuro se:

  • si riusa lo stesso IV con la stessa chiave

Per questo:

  • l’IV deve essere unico
  • meglio se casuale

Come viene usato nel codice

const cifrato = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv },
  chiave,
  messaggio
);

Qui:

  • iv viene passato come parametro all’algoritmo
  • l’algoritmo lo usa per inizializzare la cifratura

L’IV è segreto?

No

  • L’IV può essere salvato o inviato insieme al messaggio cifrato
  • Serve anche in fase di decifratura

Esempio tipico:

{
  iv: "...",
  datiCifrati: "..."
}

In sintesi

  • IV = Initialization Vector
  • Serve a rendere ogni cifratura unica e sicura
  • In AES-GCM deve essere:
    • lungo 12 byte
    • casuale
    • mai riutilizzato con la stessa chiave
  • Non è segreto, ma è obbligatorio per decifrare

Per permettere al destinatario di decifrare il messaggio, devi comunicargli l’IV che hai usato per cifrare.

Vediamo bene perché e come farlo correttamente.

Perché l’IV va inviato al ricevente

Con AES-GCM, per decifrare servono tre cose:

  1. 🔑 La chiave segreta (che il destinatario deve già avere)
  2. 🧩 Il messaggio cifrato
  3. 🧪 Lo stesso IV usato in cifratura

Se l’IV è diverso → la decifratura fallisce.

L’IV è segreto?

❌ No, non è segreto

  • Può essere inviato in chiaro
  • Può essere salvato insieme al messaggio cifrato
  • L’importante è che non venga mai riutilizzato con la stessa chiave

Come si invia l’IV di solito

Ci sono due approcci comuni:

1️⃣ IV separato dal messaggio

{
  iv: "...",
  ciphertext: "..."
}

2️⃣ IV concatenato al messaggio cifrato (molto comune)

[ IV (12 byte) | CIPHERTEXT + AUTH TAG ]

Il ricevente:

  • legge i primi 12 byte → IV
  • usa il resto come messaggio cifrato

Attenzione importante ⚠️

🔴 Mai riutilizzare lo stesso IV con la stessa chiave

Se devi cifrare molti messaggi:

  • genera sempre un IV nuovo
  • anche se il messaggio è identico

Ricorda...

✔ Sì, devi comunicare l’IV al ricevente
✔ L’IV non è segreto
✔ Senza IV corretto → niente decifratura
✔ IV unico = sicurezza


8. crypto.subtle.decrypt: decifrare il messaggio

const decifrato = await crypto.subtle.decrypt(
  { name: "AES-GCM", iv },
  chiave,
  cifrato
);

const decoder = new TextDecoder();
console.log(decoder.decode(decifrato));

Se:

  • chiave
  • IV
  • dati cifrati

sono corretti → il testo originale viene recuperato.


9. Ruolo di crypto.getRandomValues

Fuori da crypto.subtle troviamo:

crypto.getRandomValues()

Serve per:

  • IV
  • token
  • valori casuali sicuri
const random = new Uint8Array(1);
crypto.getRandomValues(random);
Se stai pensando che in JavaScript esiste già Math.random() per generare numeri causali, devi sapere che questo metodo non è adatto per la sicurezza.

Perchè Math.random() non è sicuro?
  1. è prevedibile
  2. non è progettato per la sicurezza
  3. può essere ricostruito da un attaccante

10. Riassunto finale (filo logico)

  1. crypto è la libreria principale
  2. crypto.subtle è il cuore della crittografia
  3. lavora solo con byte
  4. digest → hash
  5. generateKey → chiavi
  6. encrypt / decrypt → protezione dati

Conclusione – Recap generale

In questo articolo abbiamo visto in modo progressivo e ordinato come funziona la Crypto API di JavaScript e quale problema risolve.

Abbiamo iniziato da una panoramica generale, chiarendo che:

  • crypto è l’oggetto principale fornito da JavaScript
  • la vera crittografia è concentrata in crypto.subtle
  • questa libreria serve a proteggere i dati, non ha a che fare con le criptovalute

Successivamente siamo entrati nel funzionamento pratico della libreria, imparando che:

  • la Crypto API lavora solo con dati binari e non con stringhe
  • le stringhe devono essere convertite in byte prima di essere elaborate
  • tutte le operazioni crittografiche sono asincrone

Abbiamo poi analizzato le funzioni principali di crypto.subtle attraverso esempi concreti:

  • digest() per creare hash (come quelli usati per le password)
  • generateKey() per creare chiavi crittografiche sicure
  • encrypt() per cifrare i dati
  • decrypt() per recuperarli in modo sicuro

Infine abbiamo visto il ruolo fondamentale di crypto.getRandomValues(), indispensabile per generare valori casuali sicuri come IV, token e chiavi temporanee.

Capire questi concetti e usarli nel giusto ordine permette di scrivere applicazioni web più sicure, professionali e affidabili, evitando errori comuni e pratiche sbagliate.



Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment