Sari la conținutul principal

Semnare post-cuantică

qorechain-pqc este biblioteca open-source de criptografie post-cuantică, bazată exclusiv pe standarde, din spatele QoreChain. Aceasta oferă portofelelor, integratorilor și instrumentelor exact primitivele pe care le folosește lanțul — în șase limbaje, cu un API unic și consecvent, cu compatibilitate la nivel de octet dovedită printr-o suită comună de vectori de test inter-limbaje.

Biblioteca împachetează implementări auditate ale standardelor NIST finale. Ea nu inventează o schemă proprie: o variantă non-standard este exact ceea ce rupe interoperabilitatea (o semnătură produsă într-un loc nu s-ar verifica în altul). Fiecare binding este validat pe aceiași vectori, astfel încât o semnătură ML-DSA produsă într-un limbaj se verifică în toate celelalte, secretele partajate ML-KEM coincid în toate cele șase, iar digest-urile SHAKE-256 sunt identice.

Primitive

PrimitivăStandardRolNiveluri (implicit cu bold)
ML-DSAFIPS-204semnături digitale44 · 65 · 87
ML-KEMFIPS-203încapsulare de chei512 · 768 · 1024
SHAKE-256FIPS-202hash cu ieșire extensibilă

Acestea sunt aceleași primitive pe care QoreChain le rulează la nivel de protocol: semnături ML-DSA-87 (Dilithium-5), încapsulare de chei ML-KEM-1024 și SHAKE-256 ca hash aplicativ implicit. Vezi Securitate post-cuantică pentru modul în care lanțul le folosește.

Dimensiuni (octeți)

Alege nivelul de securitate în funcție de bugetul tău de dimensiune/securitate.

SchemăSecuritateCheie publicăSemnătură / Ciphertext
ML-DSA-44L213122420
ML-DSA-65L319523309
ML-DSA-87L525924627
ML-KEM-512L1800768
ML-KEM-768L311841088
ML-KEM-1024L515681568

Nu poți face un standard NIST mai mic și să rămână standard. ML-DSA-87 are dimensiuni fixe de cheie/semnătură și octeți ficși — „optimizarea" lui produce o variantă non-standard pe care nicio altă implementare nu o poate verifica. Pentru a reduce amprenta on-chain, folosește pârghiile de mai jos în loc să modifici schema.

Limbaje și pachete

Fiecare limbaj expune același API, fiecare fiind susținut de o implementare auditată diferită. Acesta este mecanismul care garantează compatibilitatea la nivel de octet — backend-uri independente cad de acord asupra standardului.

LimbajPachetInstalareSusținut de
JavaScript / TypeScript@qorechain/pqc (npm)npm i @qorechain/pqc@noble/post-quantum
Rustqorechain-pqc (crates.io)cargo add qorechain-pqcfips204 · fips203 · sha3
Pythonqorechain-pqc (PyPI)pip install qorechain-pqc (import qorpqc)liboqs-python
Gogithub.com/qorechain/qorechain-pqc/gogo get github.com/qorechain/qorechain-pqc/goCloudflare CIRCL
Cc/ (bibliotecă statică + header)se compilează din repoliboqs + OpenSSL
Javaio.github.qorechain:qorechain-pqc (Maven Central)io.github.qorechain:qorechain-pqc:0.1.1Bouncy Castle
Disponibilitate

Binding-urile JavaScript, Rust, Python, Go și Java sunt toate publicate la versiunea 0.1.1 — instalează-le direct din npm, crates.io, PyPI, proxy-ul de module Go și Maven Central cu comenzile de mai sus. Distribuția Python se instalează ca qorechain-pqc, dar se importă ca qorpqc. Pachetul Java este pe Maven Central ca io.github.qorechain:qorechain-pqc:0.1.1 (backend Bouncy Castle). Binding-ul C este o bibliotecă statică + header pe care le compilezi din github.com/qorechain/qorechain-pqc.

Semnare deterministă (critică pentru consens)

Începând cu versiunea 0.1.1, sign() produce varianta ML-DSA deterministă (FIPS-204 §3.4, în care randomness-ul de semnare este format din 32 de octeți zero) în toate cele șase binding-uri — și aceasta este singura variantă pe care lanțul o acceptă. Verificatorul de tranzacții al QoreChain respinge semnăturile ML-DSA hedged (randomizate), astfel că o semnătură hedged eșuează on-chain chiar dacă se verifică criptografic.

Fapte esențiale:

  • Nu schimba valoarea implicită. Semnarea deterministă este critică pentru consens; fiecare binding o documentează ca atare.
  • Ieșirea deterministă este identică la nivel de octet în toate cele șase binding-uri pentru aceeași cheie și același mesaj — garantat prin vectori de test comuni inter-limbaje.
  • Semnarea hedged rămâne disponibilă ca opțiune explicită (opt-in) per binding (de ex. {hedged: true} în JavaScript, sign_hedged în Rust, mldsaSignHedged în Java, sign(..., hedged=True) în Python) pentru cazuri de utilizare din afara lanțului — semnăturile hedged nu sunt acceptate de lanț.
  • Versiunea 0.1.0 a binding-ului JavaScript semna hedged în mod implicit — dacă ai construit instrumente de tranzacții pe 0.1.0, fă upgrade la 0.1.1; tranzacțiile semnate cu vechea valoare implicită sunt respinse on-chain.

Derivare deterministă a cheilor și recuperare

Derivarea standard a ecosistemului leagă cheia ML-DSA-87 de cont, astfel încât aceasta este recuperabilă exclusiv din mnemonicul contului:

seed = SHAKE-256("qorechain:pqc:v1|" + cosmosAddress + "|" + mnemonic)
(publicKey, secretKey) = mldsa.keygen(seed)

Fiecare instrument publicat (@qorechain/wallet-adapter, @qorechain/sdk, @qorechain/chain-bridge ≥0.1.1) derivă aceeași cheie, astfel încât un mnemonic produce o singură cheie indiferent de instrumentele folosite. Recuperează o cheie din CLI (mnemonicul pe stdin):

qorechaind tx pqc recover-key mykey qor1youraddress...
# legacy tooling derivation (shake256(mnemonic) only, unbound to the address):
qorechaind tx pqc recover-key mykey qor1youraddress... --derivation bridge

Rotația cheilor (același algoritm)

Începând cu versiunea de lanț v3.1.85, MsgRotatePQCKey rotește cheia ML-DSA-87 a unui cont în cadrul aceluiași algoritm — anterior, înregistrarea era o operațiune unică, iar MigratePQCKey traversa doar între algoritmi. Folosește-l pentru a migra o cheie derivată în mod legacy către derivarea canonică legată de adresă sau pentru a retrage o cheie compromisă.

Rotația este semnată dublu: atât cheia veche, cât și cea nouă semnează mesajul cu separare de domeniu "qorechain-pqc-rotate-v1|chainId|algorithm|account|oldPubHex|newPubHex". Replay-ul este structural imposibil — odată rotită, cheia veche nu mai corespunde cheii înregistrate, deci același mesaj nu se poate reaplica. Rotația este o operațiune exclusiv pentru cheia rădăcină (niciodată delegabilă unui authenticator), iar tranzacția în sine este în continuare semnată hibrid cu cheia veche, dovedind proprietatea curentă.

CLI într-un singur pas (mnemonicul pe stdin; recuperează cheia veche, derivă sau generează cheia nouă, semnează dublu, difuzează):

# migrate a legacy-derived key to the canonical derivation:
qorechaind tx pqc rotate-key --old-derivation bridge --new-derivation adapter \
--from mykey --chain-id qorechain-vladi -o json -y

# rotate to a brand-new random key (compromise recovery):
qorechaind tx pqc rotate-key --old-derivation adapter --new-random \
--from mykey --chain-id qorechain-vladi -o json -y

În cod, @qorechain/wallet-adapter (≥0.1.7) și @qorechain/sdk (≥0.7.0) expun același flux:

import { rotatePqcKeyMsgFromMnemonic } from "@qorechain/wallet-adapter";

// Builds the dual-signed MsgRotatePQCKey migrating shake256(mnemonic) -> canonical:
const msg = await rotatePqcKeyMsgFromMnemonic({
mnemonic, address: "qor1youraddress...", chainId: "qorechain-vladi",
});
// Sign & broadcast with the account's normal hybrid signer (old key cosigns the envelope).

După o rotație reușită, cheia nouă semnează (cod 0), iar cheia veche este respinsă (pqc cod 21).

API consecvent

Fiecare limbaj oferă aceeași suprafață:

keygen() -> (publicKey, secretKey)
sign(secretKey, message) -> signature
verify(publicKey, message, signature) -> bool

kem.keygen() -> (publicKey, secretKey)
kem.encapsulate(publicKey) -> (cipherText, sharedSecret)
kem.decapsulate(secretKey, cipherText)-> sharedSecret

shake256(data, outLen=32) -> digest

Pornire rapidă (JavaScript / TypeScript)

import { mldsa, mlkem, shake256, pubkeyHash } from '@qorechain/pqc';

// ML-DSA-87 signatures
const { publicKey, secretKey } = mldsa.keygen();
const sig = mldsa.sign(secretKey, message);
mldsa.verify(publicKey, message, sig); // true

// ML-KEM-1024 key encapsulation
const { publicKey: ek, secretKey: dk } = mlkem.keygen();
const { cipherText, sharedSecret } = mlkem.encapsulate(ek);
mlkem.decapsulate(dk, cipherText); // === sharedSecret

// SHAKE-256 + blockchain helpers
shake256(data, 32); // 32-byte digest
pubkeyHash(publicKey, 20); // pay-to-pubkey-hash

Exporturi specifice fiecărui nivel sunt disponibile acolo unde valoarea implicită nu este ceea ce vrei: mldsa44/65/87 și mlkem512/768/1024 (mldsa / mlkem sunt valorile implicite L5).

Binding-urile Rust, Go, C, Python și Java oglindesc exact acest API. De exemplu:

// Rust
use qorechain_pqc::mldsa::default as mldsa;
let (pk, sk) = mldsa::keygen()?;
let sig = mldsa::sign(&sk, msg)?;
assert!(mldsa::verify(&pk, msg, &sig));
// Go
pk, sk, _ := pqc.MLDSA.Keygen()
sig, _ := pqc.MLDSA.Sign(sk, msg)
pqc.MLDSA.Verify(pk, msg, sig) // true

Helpere pentru blockchain

Dincolo de primitivele brute, biblioteca expune două helpere de care integratorii au nevoie pentru a interacționa cu conturile și tranzacțiile QoreChain.

pubkeyHash(pk, len=20)

Un helper de înregistrare pay-to-pubkey-hash. Produce un hash SHAKE-256 scurt (20–32 de octeți) al unei chei publice. Modelul: stochează doar pubkeyHash în starea contului și cere cheia publică integrală în tranzacție. Starea contului rămâne minusculă indiferent de cheia de 1–2,5 KB.

hybridSignBytes(bodyWithoutPqcExt, authInfo)

Framing-ul QoreChain al sign-bytes cu extensie hibridă, compatibil cu portofelele. Acesta produce exact octeții care trebuie semnați cu ML-DSA-87 (Dilithium-5) pentru a forma jumătatea PQC a unei tranzacții hibride.

Aceasta este piesa pe care portofelele și integratorii o folosesc pentru a produce semnătura hibridă obligatorie pe calea de tranzacții cosmos. Începând cu versiunea curentă a lanțului, semnăturile hibride sunt obligatorii în mod implicit (hybrid_signature_mode = required, allow_classical_fallback = false): fiecare tranzacție pe calea cosmos trebuie să poarte o semnătură Dilithium-5 alături de semnătura sa clasică secp256k1. Vezi Securitate post-cuantică pentru modelul de aplicare.

Semnătura clasică secp256k1 este calculată peste sign bytes standard (care exclud extensia PQC), iar semnătura ML-DSA-87 este calculată și atașată ca extensia PQCHybridSignature. Deoarece sign bytes clasice exclud extensia, semnătura clasică rămâne validă indiferent dacă un verificator înțelege sau nu partea PQC.

Există trei moduri de a produce această semnătură hibridă:

  • CLI-ulqorechaind tx pqc cosign atașează cosemnătura Dilithium-5 unei tranzacții (după qorechaind tx pqc gen-key). Vezi Comenzi de tranzacții.
  • SDK-ul QoreChainbuildHybridTx (cu includePqcPublicKey) face echivalentul în TypeScript/Python/Go/Rust. Vezi Conturi SDK și semnare PQC.
  • qorechain-pqc direct — folosește hybridSignBytes pentru a încadra sign bytes și mldsa.sign pentru a produce semnătura Dilithium-5, atunci când construiești instrumente în afara SDK-ului într-unul dintre cele șase limbaje suportate.

Optimizarea amprentei on-chain

Cheile și semnăturile ML-DSA sunt mari după standardele clasice. Deoarece octeții unui standard sunt ficși, modul de a menține amprenta on-chain mică este să folosești aceste trei pârghii — niciuna dintre ele nu modifică standardul:

  1. Alege deliberat nivelul de securitate. Semnăturile ML-DSA-65 (L3) sunt cu ~28% mai mici decât ML-DSA-87 (L5) și rămân foarte puternice; ciphertext-urile ML-KEM-768 sunt mai mici decât cele 1024. Alege în funcție de cazul de utilizare.
  2. Pay-to-pubkey-hash. Stochează doar pubkeyHash(pk) (20–32 de octeți de SHAKE-256) în starea contului și cere cheia publică integrală în tranzacție. Starea contului rămâne minusculă indiferent de dimensiunea cheii.
  3. Semnături de tip verify-and-discard. O semnătură trebuie să existe în tranzacție (datele blocului), dar nu ar trebui niciodată scrisă în arborele de stare persistent.

De ce nu Falcon? FN-DSA (Falcon) ar oferi semnături mai mici, dar este exclus în mod intenționat: FN-DSA este FIPS-206 în stadiu de draft (nu final), iar o bibliotecă bazată exclusiv pe standarde livrează doar standarde finalizate. Poate fi reanalizat odată ce FIPS-206 este finalizat.

Resurse conexe