ML-DSA-65: semnături digitale post-cuantice conform NIST FIPS 204
ML-DSA-65 este unul dintre cele trei seturi de parametri ai algoritmului ML-DSA (Module-Lattice-Based Digital Signature Algorithm), standardizat de NIST prin FIPS 204. Este proiectat pentru generarea și verificarea semnăturilor digitale într-un scenariu în care adversarul poate dispune inclusiv de un calculator cuantic de scară mare. ML-DSA provine din familia CRYSTALS-Dilithium și este destinat autentificării, integrității datelor și semnării software-ului, documentelor, mesajelor și altor obiecte digitale.
1. De ce este necesar ML-DSA?
Algoritmii clasici de semnătură precum RSA, DSA sau ECDSA își bazează securitatea pe probleme matematice care pot fi rezolvate mult mai eficient de un calculator cuantic suficient de puternic folosind algoritmul lui Shor. Din acest motiv, infrastructurile care trebuie să rămână sigure pe termen lung trebuie să dobândească crypto-agility și să poată migra către primitive post-cuantice.
În august 2024, NIST a publicat FIPS 204, standardul care definește ML-DSA. Standardul include trei seturi de parametri: ML-DSA-44, ML-DSA-65 și ML-DSA-87. ML-DSA-65 reprezintă varianta intermediară, încadrată de NIST în Security Category 3. Categoria nu trebuie interpretată simplist ca un număr unic de „biți de securitate”, însă setul de parametri este proiectat în jurul unui nivel de robustețe asociat categoriei NIST 3, iar parametrul de collision strength λ este 192.
2. Fundamentul matematic
ML-DSA este un algoritm de semnătură bazat pe latici modulare (module lattices). Construcția folosește aritmetică polinomială într-un inel finit și paradigma Fiat-Shamir with Aborts. În termeni practici, semnatarul construiește un angajament, derivează provocarea criptografică dintr-un hash și calculează un răspuns. Dacă răspunsul nu respectă anumite limite statistice, acea încercare este abandonată și procesul este reluat. Acest mecanism de rejection sampling este o parte normală și esențială a algoritmului.
Aritmetica de bază se efectuează în inelul:
R_q = Z_q[X] / (X^256 + 1)
q = 8 380 417
Înmulțirile polinomiale sunt accelerate cu ajutorul NTT - Number Theoretic Transform. Pentru ML-DSA-65, matricea publică A are dimensiunea 6 × 5 peste acest inel.
3. Parametrii principali ai ML-DSA-65
| Parametru | Valoare ML-DSA-65 | Rol |
|---|---|---|
| q | 8 380 417 | Modulul aritmeticii polinomiale. |
| (k, l) | (6, 5) | Dimensiunile matricei A; de aici provine și sufixul „65”. |
| d | 13 | Numărul de biți eliminați/separați la operația Power2Round. |
| τ | 49 | Numărul coeficienților ±1 din polinomul de challenge c. |
| λ | 192 | Collision strength a challenge-ului comprimat. |
| η | 4 | Limita coeficienților pentru vectorii secreți. |
| β = τ × η | 196 | Parametru folosit în verificările de normă din rejection sampling. |
| γ1 | 219 | Intervalul coeficienților vectorului aleator y. |
| γ2 | (q − 1) / 32 | Parametru pentru separarea și rotunjirea componentelor high/low. |
| ω | 55 | Numărul maxim de biți 1 acceptați în vectorul de hint h. |
| Security Category | 3 | Categoria de securitate NIST revendicată pentru acest set de parametri. |
| Repetări așteptate ale buclei de semnare | 5,1 | Numărul mediu de iterații indicat de FIPS 204 pentru rejection sampling. |
4. Dimensiunea cheilor și a semnăturii
Un compromis important în criptografia post-cuantică este dimensiunea mai mare a cheilor și semnăturilor față de schemele ECC clasice. Conform FIPS 204, ML-DSA-65 folosește:
| Element | Dimensiune |
|---|---|
| Cheie privată | 4032 bytes |
| Cheie publică | 1952 bytes |
| Semnătură | 3309 bytes |
FIPS 204 menționează și posibilitatea unei reprezentări compacte a cheii private prin păstrarea seed-ului de 32 bytes și regenerarea componentelor atunci când este necesar. Această abordare reduce spațiul persistent necesar, dar implică un cost de calcul la regenerare și trebuie evaluată în funcție de arhitectura sistemului.
5. Cum este generată perechea de chei
La nivel conceptual, procesul ML-DSA.KeyGen pornește de la entropie furnizată de un generator de numere aleatoare criptografic sigur. Din seed sunt derivate valorile necesare pentru matricea publică și vectorii secreți.
Pentru ML-DSA-65, se generează doi vectori secreți mici, s1 și s2. Matricea A este determinată pseudo-aleator dintr-un seed public ρ, astfel încât nu trebuie stocată integral. Se calculează relația:
t = A · s1 + s2
Vectorul t este separat în componente de ordin înalt și de ordin scăzut. Componenta de ordin înalt t1 este inclusă în cheia publică, iar componentele necesare semnării sunt păstrate în cheia privată. Simplificat:
public_key ≈ (ρ, t1)
private_key ≈ (ρ, K, tr, s1, s2, t0)
Această descriere este intenționat conceptuală; codificarea exactă, dimensiunile și funcțiile auxiliare sunt definite normativ în FIPS 204.
6. Cum funcționează semnarea
Semnarea ML-DSA folosește paradigma Fiat-Shamir with Aborts. Fluxul poate fi rezumat astfel:
- Mesajul și contextul aplicației sunt codificate și introduse în funcția hash.
- Se obține reprezentarea criptografică μ a mesajului.
- Se generează un vector temporar y, care trebuie să fie unic/imprevizibil pentru operația de semnare.
- Se calculează angajamentul w = A · y.
- Din μ și partea relevantă a lui w se derivează challenge-ul criptografic c.
- Se calculează răspunsul z = y + c · s1.
- Se verifică limitele de normă și condițiile de hint. Dacă nu sunt respectate, încercarea este respinsă și bucla este reluată.
- Se construiește semnătura finală din challenge-ul comprimat, vectorul z și hint-ul h.
Forma conceptuală a semnăturii este:
signature = (c_tilde, z, h)
7. Cum funcționează verificarea
Verificatorul primește cheia publică, mesajul, contextul și semnătura. El decodează structurile, verifică dimensiunile și limitele impuse de standard, reconstruiește challenge-ul și compară rezultatul cu cel inclus în semnătură.
Conceptual, verificarea reconstruiește o valoare echivalentă cu:
w' ≈ A · z − c · (2^d · t1)
Hint-ul h este folosit pentru a reconstrui informația necesară din componentele rotunjite. Dacă challenge-ul recalculat este identic cu cel din semnătură și toate verificările de normă/codificare sunt corecte, semnătura este validă.
O implementare robustă trebuie să respingă explicit cheile publice și semnăturile cu lungimi incorecte. FIPS 204 tratează această verificare ca o cerință relevantă pentru proprietățile de securitate ale schemei.
8. Context string și separarea domeniilor
ML-DSA permite asocierea unui context de maximum 255 bytes operației de semnare. Contextul realizează domain separation: aceeași cheie poate fi utilizată în protocoale diferite, iar semnăturile pot fi legate explicit de un anumit protocol sau tip de obiect.
Exemple de contexte:
"FIRMWARE-OTA-V1"
"AUTOMOTIVE-ECU-CONFIG"
"DOCUMENT-SIGNING-V2"
"SOFTWARE-RELEASE-MANIFEST"
Contextul folosit la verificare trebuie să fie identic cu cel folosit la semnare.
9. Implementări și repository-uri C/C++
9.1 mldsa-native - implementarea C recomandată pentru FIPS 204
Repository: pq-code-package/mldsa-native
mldsa-native este o implementare portabilă în C90 a ML-DSA/FIPS 204, susținută de Post-Quantum Cryptography Alliance din cadrul Linux Foundation. Include backend portabil C și backend-uri optimizate pentru x86-64 și AArch64. Proiectul include verificări automate pentru memory safety, type safety și anumite clase de timing leakage și este în prezent una dintre cele mai importante implementări upstream pentru integrarea ML-DSA.
Setul de parametri se configurează la compilare. Pentru ML-DSA-65:
#define MLD_CONFIG_PARAMETER_SET 65
Proiectul oferă și opțiunea MLD_CONFIG_REDUCE_RAM, utilă pe platforme embedded,
cu un compromis între memorie și performanță.
9.2 Open Quantum Safe - liboqs
Repository: open-quantum-safe/liboqs
liboqs este o bibliotecă C care oferă o interfață comună pentru algoritmi post-cuantici. ML-DSA este standardizat și suportat direct, iar versiunile recente ale liboqs folosesc mldsa-native ca implementare primară pentru ML-DSA. Este foarte utilă pentru prototipare, benchmarking și integrarea rapidă a ML-DSA în aplicații C sau C++.
9.3 OpenSSL 3.5+
Repository: openssl/openssl
OpenSSL 3.5 include suport pentru ML-DSA-44, ML-DSA-65 și ML-DSA-87 în API-ul EVP. ML-DSA poate fi folosit pentru generare de chei, semnare și verificare. Aceasta este o opțiune importantă pentru aplicațiile care folosesc deja ecosistemul OpenSSL.
9.4 CRYSTALS-Dilithium - repository-ul de referință istoric
Repository: pq-crystals/dilithium
Acesta este repository-ul oficial al implementării de referință CRYSTALS-Dilithium și conține o variantă portabilă și una optimizată AVX2. Este extrem de util pentru studierea construcției din care a evoluat ML-DSA. Pentru un proiect nou care urmărește exact interfața și comportamentul FIPS 204, este însă preferabilă o implementare explicit actualizată pentru ML-DSA, cum este mldsa-native, liboqs sau OpenSSL.
9.5 O implementare C++20 utilă pentru studiu și prototipare
Repository: itzmeanjan/ml-dsa
Aceasta este o implementare independentă, nu un repository oficial NIST. Este scrisă în C++20, header-only și urmărește FIPS 204. Poate fi utilă în proiecte C++ și pentru înțelegerea API-urilor, dar pentru sisteme critice trebuie evaluate separat auditarea, mentenanța, vectorii de test și cerințele de certificare.
10. Exemplu practic în C cu liboqs
Următorul exemplu generează o pereche de chei ML-DSA-65, semnează un mesaj și verifică semnătura. Este un exemplu minimal și nu include persistența securizată a cheii private.
#include <oqs/oqs.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
const uint8_t message[] = "Mesaj semnat cu ML-DSA-65";
const size_t message_len = sizeof(message) - 1;
OQS_SIG *alg = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65);
if (alg == NULL) {
fprintf(stderr, "ML-DSA-65 nu este disponibil.\n");
return 1;
}
uint8_t *pk = OQS_MEM_malloc(alg->length_public_key);
uint8_t *sk = OQS_MEM_malloc(alg->length_secret_key);
uint8_t *sig = OQS_MEM_malloc(alg->length_signature);
if (pk == NULL || sk == NULL || sig == NULL) {
fprintf(stderr, "Eroare de alocare.\n");
return 1;
}
size_t sig_len = 0;
if (OQS_SIG_keypair(alg, pk, sk) != OQS_SUCCESS) {
fprintf(stderr, "KeyGen a esuat.\n");
return 1;
}
if (OQS_SIG_sign(
alg,
sig,
&sig_len,
message,
message_len,
sk) != OQS_SUCCESS) {
fprintf(stderr, "Semnarea a esuat.\n");
return 1;
}
OQS_STATUS status = OQS_SIG_verify(
alg,
message,
message_len,
sig,
sig_len,
pk
);
printf("Semnatura: %s\n",
status == OQS_SUCCESS ? "VALIDA" : "INVALIDA");
OQS_MEM_secure_free(sk, alg->length_secret_key);
OQS_MEM_insecure_free(pk);
OQS_MEM_insecure_free(sig);
OQS_SIG_free(alg);
return status == OQS_SUCCESS ? 0 : 1;
}
Compilarea liboqs
git clone -b main https://github.com/open-quantum-safe/liboqs.git
cd liboqs
mkdir build
cd build
cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr/local ..
ninja
sudo ninja install
Exemplul poate fi apoi compilat, în funcție de locația instalării:
gcc demo_mldsa65.c -o demo_mldsa65 -loqs
./demo_mldsa65
11. Exemplu cu mldsa-native
În mldsa-native, setul de parametri poate fi configurat la compilare:
#define MLD_CONFIG_PARAMETER_SET 65
Dacă se folosește același namespace simplificat mldsa ca în exemplul oficial
examples/basic, fluxul de bază arată astfel:
#include <stdint.h>
#include <string.h>
#include <mldsa_native.h>
int sign_and_verify(void)
{
const uint8_t msg[] = "Firmware image v2.4.1";
const uint8_t ctx[] = "FIRMWARE-OTA-V1";
uint8_t pk[MLDSA65_PUBLICKEYBYTES];
uint8_t sk[MLDSA65_SECRETKEYBYTES];
uint8_t sig[MLDSA65_BYTES];
if (mldsa_keypair(pk, sk) != 0)
return -1;
if (mldsa_signature(
sig,
msg, sizeof(msg) - 1,
ctx, sizeof(ctx) - 1,
sk) != 0)
return -2;
if (mldsa_verify(
sig,
msg, sizeof(msg) - 1,
ctx, sizeof(ctx) - 1,
pk) != 0)
return -3;
return 0;
}
Numele exacte ale simbolurilor pot depinde de configurația de namespace a build-ului mldsa-native.
Exemplul oficial examples/basic arată configurarea completă și include explicit avertismentul
că generatorul RNG din directorul de test nu trebuie utilizat în producție.
12. Exemplu rapid cu OpenSSL 3.5+
Generarea unei chei:
openssl genpkey -algorithm ML-DSA-65 -out mldsa65.pem
Exportarea cheii publice:
openssl pkey -in mldsa65.pem -pubout -out mldsa65-public.pem
Semnarea unui fișier:
openssl pkeyutl \
-sign \
-in firmware.bin \
-inkey mldsa65.pem \
-out firmware.bin.mldsa65.sig
Verificarea semnăturii:
openssl pkeyutl \
-verify \
-in firmware.bin \
-pubin \
-inkey mldsa65-public.pem \
-sigfile firmware.bin.mldsa65.sig
ML-DSA semnează mesajul conform mecanismului definit de FIPS 204. Nu trebuie introdus arbitrar un pas de hash extern înaintea semnării dacă protocolul nu specifică folosirea variantei HashML-DSA.
13. ML-DSA și HashML-DSA
FIPS 204 definește atât ML-DSA pentru semnarea mesajului prin interfața standard, cât și HashML-DSA, o variantă care permite pre-hashing. Pre-hashing poate fi util atunci când mesajele sunt foarte mari sau când aplicația folosește un model streaming și nu poate furniza întregul mesaj unei operații one-shot.
Alegerea nu trebuie făcută prin simpla adăugare manuală a unui SHA-256 peste mesaj. Trebuie urmată interfața și codificarea standardizată pentru HashML-DSA, pentru ca semnătura să fie interoperabilă și corect separată de alte moduri de utilizare.
14. Domenii în care ML-DSA-65 poate fi utilizat
14.1 Code signing și secure boot
Producătorul semnează firmware-ul cu cheia privată ML-DSA-65. Dispozitivul conține cheia publică sau un certificat de încredere și verifică semnătura înainte de instalarea sau pornirea imaginii. Acest model este relevant pentru IoT, embedded, echipamente industriale, gateway-uri, controlere și ECU-uri.
14.2 Actualizări OTA
Un server de update publică firmware-ul împreună cu manifestul și semnătura. Dispozitivul descarcă pachetul, verifică integritatea și autenticitatea cu ML-DSA-65 și instalează versiunea numai dacă verificarea reușește. Context strings pot separa semnăturile de firmware de semnăturile pentru configurări.
14.3 Software supply chain
ML-DSA poate semna release-uri, manifesturi, SBOM-uri, containere sau artefacte CI/CD. Cheia privată rămâne în infrastructura de signing, iar mediile de deployment verifică artefactele înainte de rulare.
14.4 PKI și certificate
ML-DSA poate fi integrat în infrastructuri PKI pentru certificate și autentificare. Suportul exact depinde însă de standardele de protocol, profilele X.509, bibliotecile criptografice și compatibilitatea dintre endpoint-uri. Într-o migrare reală trebuie verificată interoperabilitatea întregului lanț, nu doar disponibilitatea primitivei criptografice.
14.5 Documente și arhivare
Documentele, contractele, rapoartele sau logurile pot fi semnate pentru a detecta modificările și pentru a demonstra originea datelor. Pentru arhivare pe termen lung trebuie analizate separat timestamping-ul, managementul certificatelor și politica de reînnoire a semnăturilor.
14.6 Automotive și sisteme industriale
ML-DSA poate fi utilizat pentru semnarea firmware-ului ECU, configurărilor, pachetelor de update, calibrărilor și artefactelor livrate între furnizori. În astfel de sisteme trebuie evaluate suplimentar latența de boot, memoria RAM/Flash, dimensiunea transportului, Hardware Security Modules și mecanismele de rollback/anti-rollback.
14.7 Blockchain și registre distribuite
Un sistem blockchain sau un registru distribuit poate folosi ML-DSA pentru autentificarea tranzacțiilor sau a mesajelor. Integrarea nu este însă transparentă: semnăturile de 3309 bytes și cheile publice de 1952 bytes pot crește semnificativ costul de stocare și transmisie, astfel încât formatul tranzacției, consensul și limitele de bloc trebuie proiectate corespunzător.
15. Avantajele ML-DSA-65
- Standardizat de NIST prin FIPS 204.
- Proiectat pentru rezistență la atacatori care dispun de calculatoare cuantice de scară mare.
- Performanță bună pentru key generation, signing și verification pe platforme moderne.
- Nu necesită aritmetică în virgulă mobilă pentru operațiile criptografice de bază.
- Există implementări C optimizate pentru x86-64 și ARM64.
- Se integrează deja în ecosisteme precum OpenSSL și Open Quantum Safe.
- Suportă domain separation prin context strings.
- Poate fi adaptat pentru platforme embedded prin implementări optimizate și moduri de reducere a RAM.
16. Dezavantaje și aspecte practice
- Cheile și semnăturile sunt mult mai mari decât în schemele ECC moderne.
- Semnarea include rejection sampling și are timp de execuție variabil la nivel de număr de iterații.
- Implementările embedded trebuie evaluate atent din punct de vedere RAM, Flash și timp de execuție.
- Rezistența algoritmului nu elimină riscurile de side-channel, fault injection, erori de RNG sau compromiterea cheii private.
- Compatibilitatea protocoalelor și a infrastructurii PKI poate fi mai limitată decât pentru RSA/ECDSA.
- Conformitatea cu FIPS 204 nu este echivalentă cu certificarea FIPS 140 a produsului final.
17. Recomandări de implementare
- Folosiți o implementare matură, actualizată explicit pentru FIPS 204; evitați rescrierea algoritmului de la zero.
- Pentru C embedded sau integrare directă, evaluați mldsa-native.
- Pentru experimentare și API comun între mai mulți algoritmi PQC, evaluați liboqs.
- Pentru aplicații care folosesc deja OpenSSL, evaluați API-ul EVP ML-DSA din OpenSSL 3.5+.
- Folosiți un CSPRNG validat/robust și preferați semnarea hedged unde arhitectura permite.
- Protejați cheia privată folosind HSM, TPM, secure element sau o zonă hardware izolată, unde este posibil.
- Utilizați context strings pentru separarea protocoalelor și tipurilor de obiecte semnate.
- Nu reutilizați aceeași pereche de chei pentru scopuri criptografice diferite.
- Validați implementarea cu ACVP/KAT/vectori oficiali și teste negative pentru semnături corupte.
- Păstrați crypto-agility: formatul protocolului trebuie să permită schimbarea algoritmului în viitor.
18. Exemplu de arhitectură pentru firmware semnat
SERVER / CI-CD
──────────────
firmware.bin
|
v
Hash / ML-DSA input
|
v
ML-DSA-65 Sign(private_key)
|
+----------------------+
| |
v v
firmware.bin signature.bin
| |
+----------+-----------+
|
v
DEVICE / ECU
|
ML-DSA-65 Verify(public_key)
|
+------+------+
| |
VALID INVALID
| |
INSTALL REJECT
/ BOOT UPDATE
Cheia privată trebuie să rămână exclusiv în mediul de semnare. Dispozitivul are nevoie doar de cheia publică sau de mecanismul PKI necesar pentru validarea ei.
19. ML-DSA-65 versus ML-DSA-44 și ML-DSA-87
| Variantă | Categoria NIST | Cheie publică | Cheie privată | Semnătură | Poziționare |
|---|---|---|---|---|---|
| ML-DSA-44 | 2 | 1312 B | 2560 B | 2420 B | Cea mai compactă variantă ML-DSA. |
| ML-DSA-65 | 3 | 1952 B | 4032 B | 3309 B | Echilibru între nivelul de securitate și dimensiune. |
| ML-DSA-87 | 5 | 2592 B | 4896 B | 4627 B | Categoria de securitate cea mai ridicată din ML-DSA. |
20. Concluzie
ML-DSA-65 este una dintre primitivele centrale ale tranziției către criptografia post-cuantică. Standardizarea prin FIPS 204, disponibilitatea implementărilor C mature și integrarea în biblioteci precum OpenSSL și liboqs îl fac o opțiune realistă pentru proiecte noi care trebuie să introducă semnături post-cuantice.
Din punct de vedere arhitectural, ML-DSA-65 este potrivit în special acolo unde este necesar un compromis între securitate ridicată și costul de stocare/transmisie. Într-un produs real, dificultatea nu este doar alegerea algoritmului: trebuie proiectate corect managementul cheilor, domain separation, RNG-ul, protecția împotriva side-channel/fault attacks, interoperabilitatea, formatul certificatelor și strategia de crypto-agility.
21. Referințe
- NIST, FIPS 204 - Module-Lattice-Based Digital Signature Standard: https://csrc.nist.gov/pubs/fips/204/final
- NIST, PDF oficial FIPS 204: https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.204.pdf
- mldsa-native, implementare C90 ML-DSA/FIPS 204: https://github.com/pq-code-package/mldsa-native
- Open Quantum Safe, liboqs: https://github.com/open-quantum-safe/liboqs
- Open Quantum Safe, pagina ML-DSA: https://openquantumsafe.org/liboqs/algorithms/sig/ml-dsa.html
- OpenSSL 3.5, documentație EVP_PKEY ML-DSA: https://docs.openssl.org/3.5/man7/EVP_PKEY-ML-DSA/
- OpenSSL, repository oficial: https://github.com/openssl/openssl
- CRYSTALS-Dilithium, repository oficial de referință: https://github.com/pq-crystals/dilithium
- NIST ACVP - ML-DSA: https://pages.nist.gov/ACVP/draft-celi-acvp-ml-dsa.html
- Implementare C++20 independentă ML-DSA: https://github.com/itzmeanjan/ml-dsa
Articol actualizat la 10 septembrie 2026. Pentru implementări de producție verificați întotdeauna versiunea curentă FIPS 204, errata NIST, documentația bibliotecii folosite și cerințele de validare aplicabile produsului.
Susține acest blog
Cumpărând de pe https://mag.automatic-house.ro/ro/ susții blogul meu, iar 10% din vânzări vor fi direcționate către Fundația Dăruiește Viață. Îți mulțumesc!
Mulțumesc pentru atenție!
Pentru întrebări și/sau consultanță tehnică vă stau la dispoziție pe blog mai jos în secțiunea de comentarii sau pe email simedruflorin@automatic-house.ro.
O zi plăcută tuturor !
Back to top of page
