Questa è una traduzione a scopo informativo. Fa fede la versione inglese, che è quella normativa. Leggi la versione inglese

Registri degli algoritmi

I registri di identificatori per hash, AEAD, KEM, KDF e firme, e la regola di agilità che rende la migrazione post-quantistica additiva anziché incompatibile.

In Label 309 ogni scelta crittografica è indicata da un identificatore testuale tratto da un registro estensibile: sha2-256, chacha20-poly1305-stream64k, EdDSA e così via. Un record non porta mai un numero d'algoritmo grezzo né un'assunzione implicita: dichiara quale primitiva ha usato, e il verificatore cerca quell'identificatore. È questo il meccanismo dietro l'invariante agile rispetto agli algoritmi: i registri possono crescere nel tempo, e un verificatore che incontra un identificatore non implementato rifiuta il record con un errore tipizzato e stabile. Non va mai in crash, e non accetta mai in silenzio qualcosa che non è in grado di controllare.

È proprio questa regola a rendere additiva la migrazione verso gli algoritmi post-quantistici. Un nuovo identificatore è una nuova riga in una tabella, non una nuova versione del formato wire. I record più vecchi continuano a verificarsi esattamente come prima, e i verificatori più vecchi falliscono in modo sicuro davanti a record che non erano mai stati progettati per comprendere.

Due regole permanenti

In ogni registro, due vincoli sono assoluti. Le implementazioni NON DEVONO inventare crittografia nuova: ogni primitiva si riconduce a uno standard pubblico con un nome preciso. E ogni cifratura DEVE essere autenticata: sono ammessi solo i costrutti AEAD, mai un cifrario non autenticato con un controllo di integrità aggiunto a posteriori (o del tutto assente).

Hash

L'hash del contenuto è la rivendicazione primaria di ogni record, perciò il registro degli hash è quello che porta il maggior peso. Entrambe le funzioni registrate producono un digest di 32 byte, ed entrambe sono obbligatorie per un'implementazione conforme.

IdentificatoreAlgoritmoDigest
sha2-256SHA-256 (FIPS 180-4)32 B
blake2b-256BLAKE2b-256 (RFC 7693)32 B

Un produttore PUÒ calcolare l'hash dello stesso contenuto con entrambe le funzioni per ridondanza difensiva; un singolo hash è sufficiente per un record valido.

Impegno Merkle

Per impegnarsi a una lista ordinata di foglie sotto un'unica radice on-chain (sulla blockchain), Label 309 registra un solo identificatore di impegno Merkle. È la stringa registrata presso IANA per l'albero di Merkle binario SHA-256, che adotta la separazione di dominio tramite prefisso di foglia (0x00) e prefisso di nodo interno (0x01) per impedire le collisioni tra foglie e nodi.

IdentificatoreAlgoritmoRadice
rfc9162-sha256albero di Merkle binario RFC 9162, SHA-25632 B

Un albero con una sola foglia si impegna a SHA-256(0x00 ‖ leaf), non alla foglia nuda: per questo una prova su un singolo file DEVE usare un identificatore di hash semplice, mai un albero a 1 foglia.

AEAD

Il registro AEAD stabilisce quale formato di contenuto protegge un payload sigillato sul wire, cioè il campo enc.aead. Sotto enc.scheme: 1 è registrato esattamente un identificatore, ed è un formato segmentato anziché un cifrario a colpo singolo.

IdentificatoreAlgoritmoChiave / Nonce / Nonce per chunk / TagStato
chacha20-poly1305-stream64kChaCha20-Poly1305, STREAM segmentato 64 KiB32 B / 24 B / 12 B / 16 B per chunkObbligatorio, il formato del wire
aes-256-gcmAES-256-GCMRiservato (profilo futuro)

chacha20-poly1305-stream64k è ChaCha20-Poly1305 (RFC 8439) nel layout STREAM segmentato da 64 KiB della specifica age v1: il testo in chiaro è suddiviso in chunk da 65536 byte, e ogni chunk è sigillato sotto la chiave del contenuto con un nonce per chunk da 12 byte uint88_be(counter) ‖ final_flag (contatore da 0, final_flag 0x01 sull'ultimo chunk) e un AAD per chunk vuoto, producendo un tag da 16 byte per chunk. Il enc.nonce da 24 byte non è un nonce di chunk: è il salt unico per busta dell'HKDF della chiave del contenuto, ed è ciò che mantiene sicuri i nonce a contatore — la chiave del contenuto è monouso, perciò due stream non condividono mai una coppia (key, nonce) e i produttori privi di stato non coordinano mai i nonce tra le buste. Il layout segmentato permette a un verificatore di autenticare e rilasciare un payload di grandi dimensioni in modo incrementale con memoria limitata, e il flag finale rende rilevabile la troncatura. La grafia on-wire è esattamente chacha20-poly1305-stream64k; grafie alternative NON DEVONO essere prodotte. Il costrutto completo è in Sealed PoE.

chacha20-poly1305-stream64k è l'unico identificatore che può comparire come formato di contenuto on-wire. Un costrutto distinto, chacha20-poly1305 (RFC 8439, chiave da 32 byte / nonce da 12 byte / tag da 16 byte), è usato internamente per avvolgere una chiave per destinatario all'interno del costrutto sigillato: un nonce azzerato da 12 byte, l'AAD impostata alla label info del KEM scelto, che produce un wrap da 48 byte (chiave avvolta da 32 byte + tag da 16 byte). È un mattone di base, non un identificatore del wire, e un record che lo nomina in enc.aead DEVE essere rifiutato. aes-256-gcm è nominato ma inattivo; è riservato a un profilo di cifratura futuro (enc.scheme: 2) e un verificatore v1 rifiuta qualsiasi record che lo selezioni.

KEM

Il registro KEM copre i meccanismi di incapsulamento di chiave usati per indirizzare un payload sigillato a destinatari specifici. Label 309 registra un KEM classico su curva e un ibrido post-quantistico che è attivo fin dalla prima release.

IdentificatoreAlgoritmoChiave pubblica / SegretoTesto cifrato / Segreto condiviso
x25519X25519 ECDH (RFC 7748)32 B / 32 B32 B / 32 B
mlkem768x25519ibrido X-Wing (ML-KEM-768 + X25519)1216 B / 32 B1120 B / 32 B

mlkem768x25519 è il costrutto X-Wing definito in draft-connolly-cfrg-xwing-kem-10: abbina ML-KEM-768 (FIPS 203) a X25519 (RFC 7748) in modo che un attaccante debba violare entrambi per recuperare il segreto condiviso. La chiave pubblica è la chiave di incapsulamento ML-KEM-768 concatenata con la chiave pubblica X25519 (1184 B ‖ 32 B = 1216 B); il segreto è un seme da 32 byte da cui si deriva la chiave completa. Il testo cifrato di ciascun destinatario è il testo cifrato ML-KEM-768 concatenato con una chiave pubblica X25519 effimera (1088 B ‖ 32 B = 1120 B), e i due segreti condivisi vengono combinati dal combiner SHA3-256 di X-Wing (FIPS 202) nel segreto finale da 32 byte. Label 309 consuma X-Wing come KEM a scatola nera: incapsula, decapsula, il segreto condiviso da 32 byte, e non fa affidamento su alcuna proprietà dell'hashing interno del combiner. L'identificatore è scritto senza trattini interni, per allinearsi alla grafia consolidata di X-Wing.

L'ibrido viene scelto per ciascun record tramite l'intestazione di cifratura, indipendentemente dall'AEAD di contenuto. Poiché è già registrato, la confidenzialità post-quantistica è solo questione di scegliere l'identificatore, senza dover attendere una nuova versione del formato wire.

Un singolo record nomina esattamente un enc.kem, e ogni slot usa la forma di quel KEM; uno slot della forma sbagliata è ENC_SLOT_INVALID_SHAPE, un epk (≠ 32 B) o un kem_ct (≠ 1120 B) di lunghezza errata è KEM_EPK_LENGTH_MISMATCH / KEM_CT_LENGTH_MISMATCH, e un enc.kem non registrato è UNSUPPORTED_KEM_ALG. Il materiale di incapsulamento deve inoltre essere distinto all'interno di un singolo slots[]: tutti i valori epk (per x25519) o tutti i valori kem_ct (per mlkem768x25519) DEVONO differire. Un duplicato all'interno dello stesso record viene rifiutato con ENC_SLOTS_DUPLICATE_KEM_MATERIAL prima dell'esecuzione di qualsiasi primitiva KEM o AEAD, perché un epk o un kem_ct ripetuto rompe l'unicità della chiave per slot su cui si fonda l'avvolgimento a nonce azzerato. Un verificatore limita inoltre l'uso di risorse del parser prima di qualsiasi primitiva: una busta i cui slots[] superino la soglia di riferimento di 1024 slot è ENC_SLOTS_TOO_MANY, e una busta enc decodificata che superi i 65 536 byte è ENC_ENVELOPE_TOO_LARGE. Entrambe le soglie stanno ben al di sopra del tetto di ~16 KiB dei metadati Cardano che vincola qualsiasi record onesto; sono costanti applicate dal verificatore e fissate dal deployment, non campi del wire, e i deployment POSSONO restringerle.

KDF

Il registro KDF nomina le funzioni di derivazione di chiave. hkdf-sha256 deriva le chiavi all'interno del costrutto sigillato; argon2id irrobustisce una passphrase umana contro gli attacchi a forza bruta e porta con sé una soglia minima obbligatoria di parametri.

IdentificatoreAlgoritmoParametri
hkdf-sha256HKDF-SHA-256 (RFC 5869)salt (opzionale), info (opzionale), lunghezza dell'output
argon2idArgon2id (RFC 9106)memoria ≥ 65536 KiB, iterazioni ≥ 3, parallelismo ≥ 1

La soglia minima di Argon2id è normativa: un payload protetto da passphrase DEVE usare almeno 64 MiB di memoria, almeno tre iterazioni e almeno una corsia (lane). Un produttore PUÒ scegliere parametri più robusti, che viaggiano insieme al record così che un verificatore possa riprodurre la derivazione. Dove la piattaforma lo consente, i produttori DOVREBBERO impostare il parallelismo p = 4, il secondo profilo raccomandato dalla RFC 9106 §4, mentre un verificatore PUÒ accettare qualsiasi p ≥ 1, fatti salvi i tetti del deployment. Quei tetti sono un DOVREBBE per l'implementazione, non un PUÒ: un verificatore DOVREBBE imporre soglie superiori contro un denial-of-service lato verificatore provocato da parametri assurdi, segnalando ENC_PASSPHRASE_PARAMS_EXCEED_POLICY. Il tetto dipende dall'hardware ed è non normativo, e NON DEVE essere confuso con il codice della soglia minima ENC_PASSPHRASE_ARGON2_PARAMS_TOO_LOW.

Solo argon2id è selezionabile sul wire: è l'unico identificatore che un record può nominare in enc.passphrase.alg. hkdf-sha256 è un mattone di base interno: è il passo fisso di estrazione ed espansione dietro la derivazione da seme a chiave, la derivazione del KEK per slot, la chiave del MAC dell'insieme di slot, la chiave del MAC dell'impegno con passphrase e la derivazione della chiave del contenuto, e non porta alcun identificatore del wire. Un record che nomina hkdf-sha256 in enc.passphrase.alg DEVE essere rifiutato: HKDF è pensato per input ad alta entropia, non per irrobustire una passphrase a bassa entropia.

Le label interne sono costanti, mai sul wire

Il costrutto sigillato trae la sua separazione di dominio da un insieme fisso di literali di label: tag info di HKDF e prefissi SHA-256 (prefissi del salt del KEK, prefissi di trascrizione e il prefisso degli hash dell'elemento). Ciascuno è una costante di enc.scheme: 1, ASCII esatto senza terminatore né prefisso di lunghezza; nessuno viene mai serializzato, e nessuno è selezionabile attraverso alcun registro. Sono undici:

LabelRuolo
cardano-poe-kek-v1info di HKDF per il KEK per slot sul percorso x25519
cardano-poe-kek-mlkem768x25519-v1info di HKDF per il KEK per slot sul percorso mlkem768x25519
cardano-poe-x25519-kek-salt-v1prefisso SHA-256 per il salt HKDF del KEK x25519
cardano-poe-xwing-kek-salt-v1prefisso SHA-256 per il salt HKDF del KEK mlkem768x25519
cardano-poe-item-hashes-v1prefisso SHA-256 per il digest degli hash dell'elemento hashes_hash
cardano-poe-slots-transcript-v1prefisso SHA-256 per l'hash di trascrizione degli slot slots_hash
cardano-poe-slots-mac-v1info di HKDF per la chiave del MAC dell'insieme di slot
cardano-poe-passphrase-transcript-v1prefisso SHA-256 per l'hash di trascrizione della passphrase pw_hash
cardano-poe-passphrase-mac-v1info di HKDF per la chiave del MAC dell'impegno con passphrase
cardano-poe-payload-v1info di HKDF per la chiave del contenuto sul percorso a slot
cardano-poe-payload-passphrase-v1info di HKDF per la chiave del contenuto sul percorso a passphrase

Entrambi i salt del KEK condividono un'unica forma a hash etichettato — SHA-256(label ‖ enc.nonce ‖ <materiale KEM dello slot> ‖ pub_R) — sotto la propria label per KEM. Queste label sono distinte dalle stringhe info di derivazione del seme su Chiavi e dal prefisso di dominio di firma del record su Firme: l'insieme è privo di collisioni e privo di prefissi, perciò nessuna label sigillata per record è uguale a — né è un prefisso di byte di — una label di derivazione di chiave a lungo termine, e la derivazione della chiave d'identità e l'avvolgimento della chiave per record non collidono mai. Un verificatore DEVE usare ogni literale byte per byte; un solo byte divergente produce uno slots_mac, un impegno o un tag AEAD che il produttore onesto non è in grado di riprodurre. Il costrutto a livello di byte che consuma ciascuna label è su Sealed PoE.

Firma

Label 309 registra un solo algoritmo di firma. Le firme di paternità sono sempre opzionali, ma quando sono presenti vengono trasportate come COSE_Sign1 (RFC 9052) usando Ed25519.

Identificatorealg COSEAlgoritmoWrapper
EdDSA-8Ed25519 (RFC 8032)COSE_Sign1 (RFC 9052)

La verifica è stretta secondo RFC 8032 §5.1.7: le implementazioni DEVONO rifiutare le codifiche di firma non canoniche e i punti di ordine piccolo (nessuna estensione con azzeramento del cofattore). Questo coincide con i criteri di accettazione conservativi adottati dai wallet Cardano, così che una firma valida per un'implementazione conforme risulti valida per tutte.

Il supporto alle firme è indipendente dalla rivendicazione sul contenuto. Un verificatore che non implementa l'algoritmo di firma di un record contrassegna quello slot di firma come non supportato e lascia pienamente valide le rivendicazioni di timestamp e di contenuto: un algoritmo di firma sconosciuto non invalida mai il record in sé.

Identificatori riservati

Diversi identificatori sono nominati ma non ancora attivi. Segnano il percorso di migrazione concordato, così che i profili futuri usino nomi stabili e fissati in anticipo anziché stringhe improvvisate. Un produttore conforme NON DEVE emetterli, e un verificatore conforme DEVE rifiutare qualsiasi record che ne usi uno, con l'errore tipizzato corrispondente.

IdentificatoreAlgoritmoRuolo
aes-256-gcmAES-256-GCM (NIST SP 800-38D)AEAD di contenuto
ml-kem-768ML-KEM-768 (FIPS 203), autonomoKEM
ml-dsa-65ML-DSA (FIPS 204)Firma
slh-dsa-sha2-128sSLH-DSA (FIPS 205)Firma

ml-kem-768 è il KEM post-quantistico nudo, distinto dall'ibrido registrato mlkem768x25519; è l'ibrido ciò che Label 309 mette in campo, secondo il principio che un fallback classico debba restare anche dopo l'aggiunta della metà post-quantistica.

Agilità degli algoritmi e migrazione

Aggiungere un algoritmo è un'operazione autonoma e additiva: citare uno standard pubblico per la primitiva, aggiungere l'identificatore al registro appropriato, fornirne un'implementazione vagliata e ben revisionata, e pubblicare una fixture di conformità multilinguaggio così che implementazioni indipendenti concordino byte per byte. La versione del formato wire non cambia, perché lo schema non cambia: cresce soltanto l'insieme delle stringhe riconosciute.

Le conseguenze discendono direttamente dalla progettazione dei registri:

  • I vecchi record restano verificabili. I loro identificatori sono ancora nel registro, quindi ogni record esistente si verifica esattamente come il giorno in cui è stato pubblicato.
  • I vecchi verificatori falliscono in modo sicuro. Un verificatore precedente a un nuovo identificatore rifiuta i record che lo usano con un errore stabile UNSUPPORTED_*, anziché tirare a indovinare: non c'è alcun varco verso un'accettazione silenziosa.
  • Il supporto post-quantistico è additivo. Poiché mlkem768x25519 è già registrato, e poiché i nuovi KEM e le nuove firme si inseriscono nello stesso meccanismo, la transizione post-quantistica è una crescita del registro, non una migrazione incompatibile.

Un incremento della versione del formato wire è riservato a modifiche dello schema realmente incompatibili: un nuovo campo obbligatorio, un campo rimosso, un tipo cambiato. La crescita del registro non rientra mai in questa categoria, ed è proprio ciò che permette al catalogo crittografico di evolvere senza mai lasciare a piedi una prova già pubblicata.