Procedimenti di firma

SLH-DSA spiegato matematicamente

Come SLH-DSA-SHA2-256f (FIPS 205) firma senza nessun problema difficile al di fuori delle funzioni hash — dalle catene di hash agli alberi di Merkle fino alla foresta di alberi FORS.

Aggiornato: 2026-11-09

1. Di che cosa si tratta

Su McGesund i clienti con il piano Recensioni Premium e Segnali Premium possono scegliere il livello di firma PQ-Dual-Diversified. In tal caso ogni QR code porta, accanto alla classica firma Ed25519, due firme resistenti ai quanti: ML-DSA-87 e SLH-DSA-SHA2-256f.

Questo contributo spiega la seconda. È costruita in modo diverso da tutto il resto che utilizziamo.

SLH-DSA non è una cifratura. Il contenuto resta leggibile pubblicamente. SLH-DSA dimostra origine e integrità — come ogni firma digitale.

SLH-DSA sta per Stateless Hash-Based Digital Signature Algorithm. È stato sviluppato a partire da SPHINCS+ e standardizzato nel 2024 come FIPS 205. Il nome rivela già la sua particolarità: il procedimento utilizza soltanto funzioni hash. Niente reticoli, niente curve ellittiche, niente grandi numeri primi.


2. Che cosa viene firmato esattamente?

In McGesund SLH-DSA firma lo stesso insieme di dati coperto anche dalla firma Ed25519 nel QR code: il payload del QR code. Esso indica tra l'altro a quale azienda appartiene il codice (fid), di che tipo è (typ), quando è stato emesso (iat) e fino a quando è valido (exp) — come sequenza di byte codificata in forma compatta (CBOR).

Questa sequenza di byte è il nostro messaggio MM. Se qualcuno in seguito modifica un solo bit, nessuna delle firme torna più.

La firma SLH-DSA non si trova nel QR code stesso. Con circa 49 KB è di gran lunga troppo grande. È conservata come «timbro» separato presso il record del QR code nel backend di McGesund e viene caricata nel browser quando si clicca su «Verifica autenticità».


3. Perché un procedimento fatto solo di funzioni hash?

Ogni procedimento di firma si fonda su un compito praticamente irrisolvibile senza la chiave segreta:

ProcedimentoLa sicurezza si fonda su
Ed25519logaritmo discreto su una curva ellittica
FALCONvettori corti nei reticoli NTRU
ML-DSAModule-LWE e Module-SIS (reticoli)
SLH-DSAsolo sulle proprietà della funzione hash

Un grande computer quantistico romperebbe Ed25519. FALCON e ML-DSA sono considerati resistenti ai quanti — ma entrambi poggiano su problemi reticolari. Se un giorno si trovasse un attacco fondamentale ai reticoli, ne sarebbero colpiti entrambi contemporaneamente.

SLH-DSA, invece, ha bisogno soltanto che la funzione hash faccia ciò per cui è stata costruita:

Da H(x) non si puoˋ risalire a x, e nessuno trova un secondo x′ con H(x′)=H(x).\text{Da } H(x) \text{ non si può risalire a } x, \text{ e nessuno trova un secondo } x' \text{ con } H(x') = H(x).

È l'ipotesi studiata più a lungo e più a fondo dell'intera crittografia. Anche un computer quantistico qui aiuta solo in misura limitata: l'algoritmo di Grover dimezza i bit di sicurezza. Per questo la variante 256 usa valori hash di n=32n = 32 byte =256= 256 bit — dopo Grover restano comunque 128 bit.

Proprio per questo il livello si chiama Diversified: ML-DSA (reticoli) e SLH-DSA (hash) provengono da famiglie matematiche diverse. Se una cade, l'altra regge.


4. Elemento 1: firmare con le catene di hash (WOTS+)

L'idea di base è sorprendentemente semplice. Cominciamo con una sola cifra.

Si prende un valore casuale segreto ss e lo si sottopone a hash più e più volte:

s  →  H(s)  →  H2(s)  →  …  →  H15(s)=ps \;\to\; H(s) \;\to\; H^2(s) \;\to\; \dots \;\to\; H^{15}(s) = p

La fine della catena, pp, viene pubblicata. È la chiave pubblica per questa singola cifra.

Per firmare una cifra dd compresa tra 0 e 15 si rivela il valore della catena in posizione dd:

σ=Hd(s)\sigma = H^{d}(s)

Chi vuole verificare applica l'hash a σ\sigma altre 15−d15 - d volte. Se il risultato è esattamente pp, la firma è autentica:

H15−d(σ)=?pH^{15-d}(\sigma) \stackrel{?}{=} p

Un mini-esempio

Firmiamo la cifra d=6d = 6:

  • Il firmatario pubblica σ=H6(s)\sigma = H^6(s).
  • Il verificatore calcola H9(σ)=H15(s)H^{9}(\sigma) = H^{15}(s) e lo confronta con pp. Torna.

Un falsario che ha visto σ\sigma può calcolarne senza fatica H7(s)H^7(s), H8(s)H^8(s) e così via — e dunque firmare cifre più grandi. Quelle più piccole no: per farlo dovrebbe calcolare l'hash all'indietro.

Il checksum contro il «conteggio in avanti»

Affinché nessuno possa semplicemente aumentare le cifre, viene firmato in aggiunta un checksum:

C=∑i(15−di)C = \sum_{i} (15 - d_i)

Se un falsario aumenta una cifra del messaggio, CC diventa più piccolo — e per questo dovrebbe calcolare all'indietro nella catena del checksum. In questo modo entrambe le direzioni sono bloccate.

Esteso a un valore hash

Un valore hash di 32 byte ha 64 cifre in base 16. A queste si aggiungono 3 cifre di checksum:

len=64+3=67 catene\text{len} = 64 + 3 = 67 \text{ catene}

Una firma del genere si chiama WOTS+ (Winternitz One-Time Signature). Il suo grande difetto sta nel nome: one-time, cioè monouso. Chi firma due messaggi diversi con la stessa chiave rivela così tanti valori delle catene da rendere possibili le falsificazioni.


5. Elemento 2: tante chiavi monouso sotto un unico tetto (albero di Merkle)

Se ogni chiave può essere usata una sola volta, ne servono moltissime — ma si vuole pubblicare una sola chiave pubblica.

La soluzione è un albero di Merkle: le chiavi pubbliche di 2h′2^{h'} coppie WOTS+ formano le foglie. Due vicine alla volta vengono sottoposte insieme a hash, i risultati di nuovo a coppie, finché in cima rimane un'unica radice.

nodo=H(sinistra ∥ destra)\text{nodo} = H(\text{sinistra} \,\|\, \text{destra})

In SLH-DSA-SHA2-256f ogni albero ha altezza h′=4h' = 4, cioè 24=162^4 = 16 foglie.

Per dimostrare che una determinata foglia appartiene all'albero, si fornisce il percorso di autenticazione: i 4 nodi fratelli lungo il cammino verso l'alto. Con questi il verificatore risale per hash dalla foglia fino alla radice. Se ne esce la radice nota, la foglia ne fa parte.


6. Elemento 3: alberi sopra alberi (hypertree)

Naturalmente 16 chiavi monouso non bastano. Perciò SLH-DSA impila alberi uno sopra l'altro: la radice di un albero viene firmata con una chiave WOTS+ dell'albero soprastante. Questa torre si chiama hypertree.

In SLH-DSA-SHA2-256f ci sono d=17d = 17 strati, ciascuno di altezza 4:

h=d⋅h′=17⋅4=68h = d \cdot h' = 17 \cdot 4 = 68

In fondo sono quindi disponibili

268≈2,95⋅10202^{68} \approx 2{,}95 \cdot 10^{20}

foglie. La radice dell'albero più in alto si chiama PK.root\text{PK.root} — è la vera e propria chiave pubblica.

Importante: nessuno calcola questi alberi in anticipo. Tutti i valori segreti vengono derivati all'occorrenza da un valore iniziale segreto SK.seed\text{SK.seed}. Vengono memorizzati soltanto quattro valori da 32 byte ciascuno:

ParteContenutoDimensione
SK.seedvalore iniziale per tutti i valori segreti delle catene32 B
SK.prfvalore iniziale per la componente casuale RR32 B
PK.seedvalore iniziale pubblico, separa le coppie di chiavi l'una dall'altra32 B
PK.rootradice dell'albero più in alto32 B

La chiave privata è composta da tutti e quattro (128 byte), quella pubblica solo da PK.seed e PK.root (64 byte).


7. Elemento 4: una foresta contro le collisioni casuali (FORS)

Ora il vero problema: come fa il firmatario a sapere quale delle 2682^{68} foglie è ancora inutilizzata?

I procedimenti basati su hash più vecchi (XMSS, LMS) tengono a questo scopo un contatore. Questo non deve mai essere azzerato — né da un backup, né da un secondo server. Se accade comunque, una chiave monouso viene usata due volte e il procedimento è violato. Tali procedimenti si dicono con stato.

SLH-DSA è senza stato: la foglia viene scelta in modo pseudocasuale a partire dal messaggio stesso. Può allora capitare che due messaggi colpiscano la stessa foglia. Per questo in fondo non c'è una firma monouso, bensì una firma per pochi usi: FORS (Forest of Random Subsets).

FORS è composto da k=35k = 35 piccoli alberi di Merkle con 2a=29=5122^a = 2^9 = 512 foglie ciascuno. Le foglie sono valori casuali segreti.

Per firmare, l'hash del messaggio viene suddiviso in 35 numeri da 9 bit ciascuno. Ogni numero sceglie esattamente una foglia nel «proprio» albero. Per ogni albero la firma contiene:

  • il valore segreto di quella foglia
  • il suo percorso di autenticazione (9 nodi)

Per un altro messaggio un falsario dovrebbe colpire in tutti i 35 alberi foglie i cui segreti siano già stati rivelati. Anche se la stessa istanza FORS è stata usata qualche volta, è un'impresa senza speranza.


8. L'intero processo di firma

  1. Componente casuale. Da SK.prf\text{SK.prf}, un numero casuale fresco e il messaggio si ottiene un valore RR di 32 byte.
  2. Hash del messaggio.
    digest=Hmsg(R, PK.seed, PK.root, M)\text{digest} = H_{\text{msg}}(R,\ \text{PK.seed},\ \text{PK.root},\ M)
    I 49 byte del digest vengono suddivisi: 40 byte scelgono le 35 foglie FORS, il resto determina quale albero (idx_tree) e quale foglia (idx_leaf) in fondo all'hypertree vengono usati.
  3. Firma FORS sul messaggio. Ne risulta una chiave pubblica FORS.
  4. Firma dell'hypertree su questa chiave FORS: 17 firme WOTS+, ciascuna con un percorso di autenticazione, strato dopo strato fino a PK.root\text{PK.root}.

La firma finita è semplicemente la concatenazione:

σ=R ∥ σFORS ∥ σHT\sigma = R \,\|\, \sigma_{\text{FORS}} \,\|\, \sigma_{\text{HT}}

9. Perché la firma è grande 49.856 byte

Con i parametri di SLH-DSA-SHA2-256f la dimensione si può ricalcolare esattamente (n=32n = 32 byte per valore hash):

ParteCalcoloByte
RRnn32
FORSk⋅(1+a)⋅n=35⋅10⋅32k \cdot (1 + a) \cdot n = 35 \cdot 10 \cdot 3211.200
Hypertree(h+d⋅len)⋅n=(68+17⋅67)⋅32(h + d \cdot \text{len}) \cdot n = (68 + 17 \cdot 67) \cdot 3238.624
Totale49.856

Per confronto: una firma Ed25519 ha 64 byte, ML-DSA-87 ne ha 4.627. La dimensione è il prezzo che SLH-DSA paga per cavarsela con nient'altro che funzioni hash.


10. Come verifica il browser

Con SLH-DSA verificare significa: ricalcolare gli hash.

  1. Ricalcolare il digest da RR, chiave pubblica e messaggio.
  2. Dalle 35 foglie FORS rivelate e dai loro percorsi calcolare le 35 radici degli alberi e da queste la chiave pubblica FORS.
  3. Con ciascuna delle 17 firme WOTS+ portare a termine gli hash delle catene, formare la chiave pubblica WOTS+ e risalire per hash lungo il percorso fino alla radice dell'albero.
  4. Alla fine deve risultare esattamente PK.root\text{PK.root}.

Sono alcune migliaia di chiamate hash — per un computer una bazzecola. Nel browser, da noi, la verifica richiede circa da 6 a 12 millisecondi.


11. Che cosa succede se qualcuno modifica i dati?

Se cambia anche un solo bit del messaggio MM, il digest cambia completamente. I 35 numeri puntano allora ad altre foglie FORS e il procedimento a un altro punto dell'hypertree.

I segreti rivelati non combaciano più: le radici ricalcolate divergono e alla fine non risulta PK.root\text{PK.root}. La verifica fallisce.

Per costruire comunque una firma valida, un attaccante dovrebbe conoscere segreti mai pubblicati — dovrebbe cioè calcolare una funzione hash all'indietro.


12. Perché proprio 256f?

FIPS 205 definisce dodici insiemi di parametri: due famiglie di hash (SHA-2 e SHAKE), tre livelli di sicurezza (128, 192, 256) e per ciascuno una variante veloce («f») e una piccola («s»).

VarianteFirmaFirmare (da noi)Verificare
SHA2-256s29.792 Bca. 2,6 sca. 3 ms
SHA2-256f49.856 Bca. 0,26 sca. 6 ms

256 significa categoria di sicurezza NIST 5 — lo stesso livello di FALCON-1024 e ML-DSA-87.

Abbiamo scelto «f» perché le aziende possono emettere fino a 500 QR code in un colpo solo. Con «s» la firma richiederebbe oltre 20 minuti, con «f» meno di un minuto. In compenso la firma è più grande — poiché non sta nel QR code, è sostenibile.

SHA-2 anziché SHAKE, perché SHA-256 e SHA-512 sono accelerati in hardware praticamente su ogni dispositivo.


13. Il caso nella firma

FIPS 205 consente due modi di generare RR:

  • deterministico: stesso messaggio, stessa firma
  • randomizzato («hedged»): vi confluisce un numero casuale fresco

Noi usiamo la variante randomizzata. Due firme sullo stesso messaggio hanno quindi un aspetto diverso — entrambe sono valide. Ciò rende più difficili gli attacchi che combinano misurazioni sul dispositivo (consumo di corrente, tempo) con firme ripetute.


14. Che cosa ne fa concretamente McGesund

Il livello. PQ-Dual-Diversified è disponibile in Recensioni Premium e Segnali Premium. Un QR code porta allora tre firme:

FirmaFamigliaPosizione
Ed25519curva ellitticanel QR code
ML-DSA-87reticolitimbro nel backend
SLH-DSA-SHA2-256ffunzioni hashtimbro nel backend

La firma. Una firma SLH-DSA costa circa un quarto di secondo di tempo di calcolo. Affinché nel frattempo il server resti raggiungibile per tutti gli altri, i calcoli vengono svolti da thread in background dedicati.

La verifica. Il browser del lettore carica entrambi i timbri e li verifica con lo stesso modulo WASM usato per tutte le altre firme PQ. Noi forniamo i dati; i calcoli avvengono sul dispositivo del visitatore.

Il confronto con NIST. Il nostro modulo supera i vettori di test ufficiali NIST per SLH-DSA-SHA2-256f: dai valori iniziali di NIST nascono byte per byte le stesse chiavi, e tutte le firme manipolate di proposito vengono respinte. Può verificarlo Lei stesso nel browser sulla pagina di test NIST.

L'ancoraggio temporale. Come per tutte le chiavi, l'impronta digitale della chiave SLH-DSA viene ancorata tramite OpenTimestamps in un blocco Bitcoin.


15. SLH-DSA, ML-DSA e FALCON a confronto

ProprietàFALCON (FN-DSA)ML-DSA-87SLH-DSA-SHA2-256f
Fondamentoreticoli NTRUreticoli modularisolo funzioni hash
StandardFIPS 206 (in lavorazione)FIPS 204, definitivoFIPS 205, definitivo
Chiave pubblica1.793 B2.592 B64 B
Firma1.280 B4.627 B49.856 B
Firmaremillisecondimillisecondica. 0,26 s
Verificaremillisecondimillisecondimillisecondi
Ipotesiproblema reticolareproblema reticolarefunzione hash

In breve: SLH-DSA è il più lento e il più grande dei tre procedimenti — e il più conservativo. Non si basa su nulla che ogni altra firma non presupponga già comunque: una funzione hash sicura.


16. Una frase da portare a casa

SLH-DSA firma con catene di hash, le raggruppa in alberi di Merklee sceglie la foglia dal messaggio stesso — sicuro fincheˊla funzione hash eˋ sicura.\boxed{ \begin{array}{c} \text{SLH-DSA firma con catene di hash, le raggruppa in alberi di Merkle}\\ \text{e sceglie la foglia dal messaggio stesso — sicuro finché}\\ \text{la funzione hash è sicura.} \end{array}}

Chi possiede il valore iniziale segreto firma in un quarto di secondo. Chi non lo possiede dovrebbe calcolare SHA-256 o SHA-512 all'indietro — anche con un computer quantistico.

Per il lettore di una recensione ciò significa: anche se un giorno dovessero cadere tutti i procedimenti basati su reticoli, questa firma resta verificabile. Non deve crederci. Può ricalcolare.