GoSuda

Az MLDSA és MLKEM használata a Go nyelvben

By snowmerak
views ...

Áttekintés

Háttér

Már régóta fenyegetésként tekintenek a kvantumszámítógépek gyors számítási képességére a meglévő titkosítási rendszerekre. Ez azért van, mert a meglévő RSA vagy ECC rendszereket fel lehetne törni a kvantumszámítógépek ilyen számítási teljesítménye miatt. Azonban néhány évvel ezelőtt a kvantumszámítógépek koncepciója egyre inkább kézzelfoghatóvá vált, és alternatív megoldásokat kezdtek kutatni és fejleszteni, a NIST pedig a PQC (Poszt-kvantum kriptográfia) szabványosításán dolgozott.

MLDSA és MLKEM

Végül a NIST 2024 augusztusában szabványosította az MLKEM-et és az MLDSA-t, amelyek a CRYSTALS-Kyber és CRYSTALS-Dilithium alapjain nyugszanak. Mindkét algoritmus az MLWE (Module Learning with Errors) problémán alapul. Ezt a formát rácsalapú kriptográfiának nevezzük.

A rácsalapú kriptográfia, ahogy a neve is sugallja, egy kriptográfiai rendszer, amely egy rács matematikai problémájának nehézségén alapul. Bár nekem nincs mélyreható matematikai tudásom erről, egy mondatban összefoglalva: „egy olyan probléma, amelyben zajos lineáris egyenleteket kell megoldani egy moduláris rácsban”. Nem tudom, mennyire nehéz ez, de állítólag annyira bonyolult, hogy még kvantumszámítógépekkel sem oldható meg.

MLDSA

Először tekintsük át az MLDSA-t.

Felépítés

Az MLDSA, ahogy a neve is mutatja, egy aszimmetrikus aláírási algoritmus, amely a következő 2 fázison megy keresztül:

  1. Aláírás generálása: Privát kulcs segítségével aláírás generálása egy üzenethez.
  2. Aláírás ellenőrzése: A generált aláírás érvényességének ellenőrzése a nyilvános kulcs segítségével.

Az MLDSA a következő 3 tulajdonsággal rendelkezik:

  1. strong existential unforgeability: Egy aláírás és egy nyilvános kulcs alapján nem lehet más érvényes aláírást generálni.
  2. chosen message attack: Bármely üzenet aláírása alapján, a nyilvános kulccsal nem lehet új érvényes aláírást generálni.
  3. side-channel attack: Az aláírás során folyamatosan új véletlen értékeket és az üzenetből származó pszeudovéletlen értékeket használ, ami magas biztonságot eredményez.
  4. domain separation: Különböző seed-eket használ különböző paraméterekhez, megelőzve az ismétlődő biztonsági problémákat.

Kód

Most bemutatok egy egyszerű Go nyelven írt példakódot. Ebben a példában a cloudflare/circl mldsa implementációját használtuk.

 1package main
 2
 3import (
 4	"crypto"
 5	"crypto/rand"
 6	"encoding/base64"
 7	"fmt"
 8
 9	"github.com/cloudflare/circl/sign/mldsa/mldsa44"
10)
11
12func main() {
13    // Kulcsok generálása az mldsa44 specifikáció szerint.
14	pub, priv, err := mldsa44.GenerateKey(rand.Reader)
15	if err != nil {
16		panic(err)
17	}
18
19	message := []byte("Hello, World!")
20
21    // Aláírás generálása.
22    // Egy megjegyzés: a jelenlegi verzió (2024. december 22.) szerint, ha nem crypto.Hash(0) van megadva, hiba történik.
23	signature, err := priv.Sign(rand.Reader, message, crypto.Hash(0))
24	if err != nil {
25		panic(err)
26	}
27
28	encodedSignature := base64.URLEncoding.EncodeToString(signature)
29	fmt.Println(len(encodedSignature), encodedSignature)
30
31    // Az ellenőrzés a nyilvános kulcs scheme metódusának meghívásával történik.
32	ok := pub.Scheme().Verify(pub, message, signature, nil)
33	fmt.Println(ok)
34}
13228 oaSaOA-...
2true

Az aláírás értéke túl hosszú, ezért kihagytuk. Ha látni szeretné a teljes szöveget, futtassa a playground oldalon.

Még ha base64-gyel is kódolták, a 3228 bájtos méret kissé megterhelő lehet. Kicsit aggasztó, hogy hamarosan ilyen méretű aláírásokat kell cserélnünk a kvantumszámítógépek elleni védelem érdekében.

MLKEM

Felépítés

Az MLKEM egy kulcskapszulázási mechanizmus (Key Encapsulation Mechanism). A KEM egy olyan algoritmus, amely lehetővé teszi két fél közötti megosztott kulcs létrehozását nyilvános kulcsú titkosítás segítségével. Az MLKEM kulcscsere mechanizmusa a következő lépéseken megy keresztül:

  1. Kulcskapszulázás: A feladó a címzett nyilvános kulcsát használja egy titkosított üzenet (cipher text) és egy megosztott kulcs (shared key) létrehozására. Ezt a titkosított üzenetet kezdetben elküldi a címzettnek használatra.
  2. Kulcskapszulázás feloldása: A címzett a saját privát kulcsát használja a megosztott kulcs kinyerésére a titkosított üzenetből.

Az MLKEM-nek összesen 3 paramétere létezik: MLKEM-512, MLKEM-768, MLKEM-1024. Minél kisebb a szám, annál kisebb kulcs és titkosított szöveg keletkezik, minél nagyobb, annál hosszabb kulcs és titkosított szöveg keletkezik, és annál magasabb a biztonsági szint.

Kód

Az MLKEM a go 1.24-ben kerül bevezetésre, ezért a jelenleg elérhető go 1.24rc1-et használtuk.

 1package main
 2
 3import (
 4	"crypto/mlkem"
 5	"encoding/base64"
 6	"fmt"
 7)
 8
 9func main() {
10    // Létrehozza a címzett PrivateKey-ét.
11	receiverKey, err := mlkem.GenerateKey1024()
12	if err != nil {
13		panic(err)
14	}
15
16    // Az MLKEM-ben a PublicKey helyett az EncapsulationKey kifejezést használják.
17	receiverPubKey := receiverKey.EncapsulationKey()
18
19    // Egyszerűen megmutatjuk, hogy az EncapsulationKey Bytes() és NewEncapsulationKeyX segítségével a kulcs kinyerhető és újra felhasználható.
20    // Természetesen a valóságban ez a folyamat azt jelenti, hogy a feladó objektummá alakítja a címzett EncapsulationKey kulcsát, amely szövegesen nyilvános.
21	clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
22	if err != nil {
23		panic(err)
24	}
25
26    // Az Encapsulate metódussal a feladó létrehozza a titkosított szöveget és a megosztott kulcsot.
27	cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()
28
29    // Szándékosan klónoztuk a címzett privát kulcsát, hogy megmutassuk, hogyan tárolható és hívható elő.
30	clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
31	if err != nil {
32		panic(err)
33	}
34
35    // A címzett a privát kulcsát használva Decapsulate-eli a titkosított szöveget, és egy másik megosztott kulcsot generál.
36	sharedKeyReceiver, err := clonedReceiverKey.Decapsulate(cipherText)
37	if err != nil {
38		panic(err)
39	}
40
41	fmt.Println(base64.StdEncoding.EncodeToString(SenderSharedKey))
42	fmt.Println(base64.StdEncoding.EncodeToString(sharedKeyReceiver))
43}
1Q1ciS818WFHTK7D4MTvsQvciMTGF+dSGqMllOxW80ew=
2Q1ciS818WFHTK7D4MTvsQvciMTGF+dSGqMllOxW80ew=

Látható, hogy azonos méretű megosztott kulcsok jönnek létre!

Ez a kód a játszótéren is megtekinthető.

Konklúzió

Az egyes algoritmusok specifikációi, biztonsági szintjei, privát kulcsai, nyilvános kulcsai, aláírásai és titkosított üzeneteinek méretei a következőképpen foglalhatók össze. Mindegyik büszkén viseli a PQC nevet, és meglehetősen nagy méretű.

AlgoritmusNIST biztonsági szintPrivát kulcs méreteNyilvános kulcs méreteAláírás/titkosított üzenet mérete
ML-DSA-4422,5601,3122,420
ML-DSA-6534,0321,9523,309
ML-DSA-8754,8962,5924,627
ML-KEM-51211,632800768
ML-KEM-76832,4001,1841,088
ML-KEM-102453,1681,5681,568

Ezen algoritmusok segítségével reméljük, hogy a kvantumszámítógépek korában is biztonságosan használhatjuk az internetet, azonban a megnövekedett kulcs- és aláírás/titkosított üzenetméretek miatt elkerülhetetlennek tűnik a több számítási művelet.

Mindazonáltal a Go nyelv hatékonyan implementálja az egyes algoritmusokat, ezért reméljük, hogy aktívan felhasználják majd az Önök biztonságának megőrzésére a megfelelő helyeken!