GoSuda

Bruk av MLDSA og MLKEM i Go-språket

By snowmerak
views ...

Oversikt

Bakgrunn

Helt siden lenge tilbake har den raske databehandlingen til kvantedatamaskiner blitt ansett som en trussel mot eksisterende krypteringssystemer. Eksisterende systemer som RSA eller ECC kan potensielt dekodes på grunn av kvantedatamaskinens databehandlingskapasitet. Men for noen år siden begynte konseptet kvantedatamaskin å ta form, og alternativer ble forsket på og utviklet, og NIST har drevet standardisering av PQC (Post-Quantum Cryptography).

MLDSA og MLKEM

Til slutt vedtok NIST MLKEM og MLDSA basert på CRYSTALS-Kyber og CRYSTALS-Dilithium som standard i august 2024. Begge algoritmene opererer basert på problemet MLWE (Module Learning with Errors). Vi kaller denne formen gitterbasert kryptografi.

Gitterbasert kryptografi er, som navnet antyder, et krypteringssystem basert på vanskeligheten av matematiske problemer på et gitter. Jeg har ikke inngående matematisk kunnskap om dette, men for å oppsummere det i én setning, er det problemet med å løse støyende lineære ligninger i et modulært gitter. Jeg er usikker på hvor vanskelig det er, men det sies at dette problemet er så vanskelig at det ikke kan løses selv med en kvantedatamaskin.

MLDSA

La oss først se på MLDSA.

Konfigurasjon

MLDSA er, som navnet antyder, en asymmetrisk signaturalgoritme og består av følgende to trinn:

  1. Signaturgenerering: Genererer en signatur for en melding ved hjelp av en privat nøkkel
  2. Signaturverifisering: Verifiserer gyldigheten av den genererte signaturen ved hjelp av en offentlig nøkkel

Og MLDSA har følgende tre egenskaper:

  1. strong existential unforgeability: Det er ikke mulig å generere en annen gyldig signatur med én signatur og en offentlig nøkkel.
  2. chosen message attack: Det er ikke mulig å generere en ny gyldig signatur med en offentlig nøkkel, selv med en signatur for en gitt melding.
  3. side-channel attack: Høy sikkerhet oppnås ved kontinuerlig å bruke nye tilfeldige verdier og pseudo-tilfeldige verdier avledet fra meldinger ved signering.
  4. domain separation: Forhindrer gjentatte sikkerhetsproblemer ved å bruke forskjellige seed for forskjellige parametere.

Kode

La meg vise deg et enkelt Go-språkkodeeksempel. Dette eksemplet bruker mldsa fra cloudflare/circl.

 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    // Generer en nøkkel med mldsa44-spesifikasjonen.
14	pub, priv, err := mldsa44.GenerateKey(rand.Reader)
15	if err != nil {
16		panic(err)
17	}
18
19	message := []byte("Hello, World!")
20
21    // Generer en signatur.
22    // En ting å merke seg er at per 22. desember 2024, oppstår det en feil med gjeldende versjon med mindre crypto.Hash(0) brukes.
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    // Verifiser ved å kalle skjemaet til den offentlige nøkkelen.
32	ok := pub.Scheme().Verify(pub, message, signature, nil)
33	fmt.Println(ok)
34}
13228 oaSaOA-...
2true

Jeg har utelatt signaturverdien fordi den er for lang. Hvis du vil se hele teksten, kan du kjøre den på playground.

Selv om den er base64-kodet, er det litt byrdefullt å ha 3228 bytes. Jeg synes det er litt byrdefullt å tenke på at vi kanskje må utveksle denne størrelsen som en signatur mot kvantedatamaskiner snart...

MLKEM

Konfigurasjon

MLKEM er en Key Encapsulation Mechanism. KEM er en algoritme som lar to parter generere en felles nøkkel ved hjelp av public-key cryptography. Nøkkelutvekslingsmekanismen til MLKEM følger følgende prosess:

  1. Nøkkekapsling: Avsenderen genererer en kryptert melding (cipher text) og en felles nøkkel (shared key) ved hjelp av mottakerens offentlige nøkkel. Denne krypterte meldingen overføres initialt til mottakeren for bruk.
  2. Nøkkekapseldekaplsering: Mottakeren bruker sin private nøkkel til å trekke ut den felles nøkkelen fra den krypterte meldingen.

Det finnes totalt tre parametere i MLKEM. MLKEM-512, MLKEM-768 og MLKEM-1024 eksisterer. Jo mindre tallet er, desto mindre nøkkel og krypteringstekst produseres, og jo større tallet er, desto lengre nøkkel og krypteringstekst produseres, og desto høyere er sikkerhetsnivået.

Kode

MLKEM vil bli lagt til i go 1.24, så jeg brukte go 1.24rc1, som er tilgjengelig på dette tidspunktet.

 1package main
 2
 3import (
 4	"crypto/mlkem"
 5	"encoding/base64"
 6	"fmt"
 7)
 8
 9func main() {
10    // Generer mottakerens PrivateKey.
11	receiverKey, err := mlkem.GenerateKey1024()
12	if err != nil {
13		panic(err)
14	}
15
16    // MLKEM bruker begrepet EncapsulationKey i stedet for PublicKey.
17	receiverPubKey := receiverKey.EncapsulationKey()
18
19    // Jeg dupliserte det for å vise at nøkkelen kan trekkes ut og brukes på nytt enkelt med Bytes() og NewEncapsulationKeyX i EncapsulationKey.
20    // Selvfølgelig, hvis den brukes i virkeligheten, kan du se på denne prosessen som at avsenderen lager en objekt av mottakerens EncapsulationKey, som ble offentliggjort som tekst.
21	clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
22	if err != nil {
23		panic(err)
24	}
25
26    // Avsenderen genererer krypteringsteksten og den felles nøkkelen med Encapsulate.
27	cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()
28
29    // Jeg dupliserte den med vilje for å vise lagring og henting av mottakerens private nøkkel.
30	clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
31	if err != nil {
32		panic(err)
33	}
34
35    // Mottakeren genererer en annen felles nøkkel ved å Decapsulate krypteringsteksten ved hjelp av sin private nøkkel.
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=

Som et resultat kan du se at det genereres en felles nøkkel av samme størrelse!

Denne koden kan også verifiseres på playground.

Konklusjon

Spesifikasjonene, sikkerhetsnivåene og størrelsen på den private nøkkelen, den offentlige nøkkelen og signaturen eller chifferteksten for hver algoritme kan oppsummeres som følger. Hver av dem har store størrelser som passer et navn som PQC.

AlgoritmeNIST sikkerhetsnivåPrivat nøkkelstørrelseOffentlig nøkkelstørrelseSignatur/chiffertekststørrelse
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

Vi håper at vi kan bruke et trygt internett selv på kvantedatamaskiner ved hjelp av disse algoritmene, men det ser ut til at mer databehandling vil være uunngåelig på grunn av de relativt store nøkkel- og signatur-/chiffertekststørrelsene.

Likevel håper vi at Go-språket vil bli aktivt brukt til å beskytte sikkerheten din på passende steder, siden hver algoritme er effektivt implementert!