---
id: df2ea4cfe0d5ec72a92e1b3cfd4156f2
author: snowmerak
title: Zkušenosti s používáním MLDSA a MLKEM v jazyce Go
description: Go 언어에서 양자 내성 암호화 MLDSA와 MLKEM 사용법을 알아보고, 각 알고리즘의 특징과 코드 예제를 제공합니다.
language: cs
date: 2024-12-22T08:17:58.797764292Z
path: /blog/posts/usage-of-mldsa-and-mlkem-in-the-go-language-zb0442110
category: security
---

## Přehled

### Pozadí

Už poměrně dlouho je rychlé výpočetní řešení kvantových počítačů vnímáno jako hrozba pro stávající kryptografické systémy. Je tomu tak proto, že tradiční systémy RSA a ECC by mohly být díky této výpočetní schopnosti kvantových počítačů prolomeny. Před několika lety se však koncept kvantových počítačů začal konkretizovat, a proto začaly být zkoumány a vyvíjeny jejich alternativy; NIST zároveň pokračuje v standardizaci PQC (post-kvantové kryptografie).

### MLDSA a MLKEM

Nakonec NIST v srpnu 2024 přijal jako standardy MLKEM a MLDSA, které vycházejí z CRYSTALS-Kyber a CRYSTALS-Dilithium. Oba algoritmy fungují na základě problému MLWE (Module Learning with Errors). Tento typ označujeme jako kryptografii založenou na mřížkách.

Kryptografie založená na mřížkách je, jak už název napovídá, kryptografický systém založený na obtížnosti matematických úloh nad mřížkami. Ani já nemám hluboké matematické znalosti v této oblasti, ale shrnuto do jedné věty se říká, že jde o `problém řešení lineárních rovnic s šumem v modulární mřížce`. Není mi jasné, jak obtížný tento problém je, ale říká se, že je natolik náročný, že jej nelze vyřešit ani kvantovými počítači.

## MLDSA

Nejprve se tedy podívejme na MLDSA.

### Struktura

Jak již napovídá název, MLDSA je asymetrický podpisový algoritmus, který prochází následujícími dvěma kroky:

1. Generování podpisu: vytvoření podpisu zprávy pomocí soukromého klíče
2. Ověření podpisu: ověření platnosti vygenerovaného podpisu pomocí veřejného klíče

MLDSA dále disponuje těmito čtyřmi vlastnostmi:

1. Silná existenční nepadělatelnost (strong existential unforgeability): z jednoho podpisu a veřejného klíče nelze vytvořit jiný platný podpis.
2. Útok volenou zprávou (chosen message attack): ani podpis libovolné zprávy nedovolí s použitím veřejného klíče vytvořit nový platný podpis.
3. Postranní kanálové útoky (side-channel attack): při podepisování se neustále používají nové náhodné hodnoty a pseudonáhodné hodnoty odvozené ze zprávy, což zvyšuje bezpečnost.
4. Oddělení domén (domain separation): pro různé parametry se používají různé seedy, čímž se předchází opakovaným bezpečnostním problémům.

### Kód

Nyní si ukažme jednoduchý příklad kódu v jazyce Go.
V tomto příkladu byl použit modul mldsa z [cloudflare/circl](github.com/cloudflare/circl).

```go
package main

import (
	"crypto"
	"crypto/rand"
	"encoding/base64"
	"fmt"

	"github.com/cloudflare/circl/sign/mldsa/mldsa44"
)

func main() {
    // Vygenerujeme klíč podle specifikace mldsa44.
	pub, priv, err := mldsa44.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}

	message := []byte("Hello, World!")

    // Vytvoříme podpis.
    // Jedna věc, na kterou je třeba dát pozor: podle verze aktuální k 22. prosinci 2024 dojde k chybě, pokud crypto.Hash(0) není použito.
	signature, err := priv.Sign(rand.Reader, message, crypto.Hash(0))
	if err != nil {
		panic(err)
	}

	encodedSignature := base64.URLEncoding.EncodeToString(signature)
	fmt.Println(len(encodedSignature), encodedSignature)

    // Ověření provedeme voláním scheme veřejného klíče.
	ok := pub.Scheme().Verify(pub, message, signature, nil)
	fmt.Println(ok)
}
```

```
3228 oaSaOA-...
true
```

> Hodnota podpisu je příliš dlouhá, proto byla vynechána. Pokud si chcete prohlédnout úplný výstup, spusťte kód na [playground](https://go.dev/play/p/nqbUnKpFW3j).

I když je podpis zakódován pomocí base64, délka 3228 bajtů je poměrně znepokojivá.
Když si uvědomíme, že v budoucnu budeme možná muset takto velké podpisy vyměňovat jako ochranu proti kvantovým počítačům, je to trochu znepokojivé...

## MLKEM

### Struktura

MLKEM je mechanismus zapouzdření klíče (Key Encapsulation Mechanism). KEM je algoritmus, který pomocí asymetrické kryptografie umožňuje vytvořit sdílený klíč mezi dvěma stranami. Výměna klíčů v MLKEM probíhá následovně:

1. Zapouzdření klíče: odesílatel pomocí veřejného klíče příjemce vytvoří zašifrovanou zprávu (cipher text) a sdílený klíč (shared key). Tuto zašifrovanou zprávu odešle příjemci, aby ji mohl použít.
2. Rozbalení klíče: příjemce pomocí svého soukromého klíče extrahuje sdílený klíč ze zašifrované zprávy.

MLKEM má celkem 3 parametry: MLKEM-512, MLKEM-768 a MLKEM-1024. Čím nižší číslo, tím menší klíče a šifrovaný text; čím vyšší číslo, tím delší klíče a šifrovaný text a tím vyšší úroveň zabezpečení.

### Kód

Protože MLKEM bude přidán až v Go 1.24, byla použita verze go 1.24rc1, která je k dispozici již nyní.

```go
package main

import (
	"crypto/mlkem"
	"encoding/base64"
	"fmt"
)

func main() {
    // Vytvoříme soukromý klíč příjemce.
	receiverKey, err := mlkem.GenerateKey1024()
	if err != nil {
		panic(err)
	}

    // MLKEM nepoužívá termín PublicKey, ale EncapsulationKey.
	receiverPubKey := receiverKey.EncapsulationKey()

    // Pro jednoduchost jsme klíč EncapsulationKey zkopírovali, abychom ukázali, že jej lze extrahovat pomocí Bytes() a znovu použít pomocí NewEncapsulationKeyX.
    // V praxi tento krok odpovídá tomu, že odesílatel z veřejně zveřejněného textového EncapsulationKey příjemce vytvoří objekt.
	clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
	if err != nil {
		panic(err)
	}

    // Pomocí Encapsulate odesílatel vytvoří šifrovaný text a sdílený klíč.
	cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()

    // Zkopírovali jsme soukromý klíč příjemce záměrně, abychom ukázali uložení a načtení soukromého klíče.
	clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
	if err != nil {
		panic(err)
	}

    // Příjemce pomocí soukromého klíče provede Decapsulate šifrovaného textu a vytvoří další sdílený klíč.
	sharedKeyReceiver, err := clonedReceiverKey.Decapsulate(cipherText)
	if err != nil {
		panic(err)
	}

	fmt.Println(base64.StdEncoding.EncodeToString(SenderSharedKey))
	fmt.Println(base64.StdEncoding.EncodeToString(sharedKeyReceiver))
}
```

```sh
Q1ciS818WFHTK7D4MTvsQvciMTGF+dSGqMllOxW80ew=
Q1ciS818WFHTK7D4MTvsQvciMTGF+dSGqMllOxW80ew=
```

Výsledkem je, že se vytvoří sdílený klíč stejné velikosti, což lze ověřit!

Tento kód si můžete prohlédnout také na [playground](https://go.dev/play/p/n_cxNp435Qn?v=gotip).

## Závěr

Specifikace jednotlivých algoritmů, úrovně zabezpečení a velikosti soukromých klíčů, veřejných klíčů, podpisů a šifrovaných textů lze shrnout do následující tabulky. Každý z nich si vede s názvem PQC dobře a nabízí značné rozměry.

| Algoritmus  | Úroveň zabezpečení NIST | Velikost soukromého klíče | Velikost veřejného klíče | Velikost podpisu/šifrovaného textu |
| ----------- | ----------------------- | ------------------------- | ------------------------ | ---------------------------------- |
| ML-DSA-44   | 2                       | 2,560                     | 1,312                    | 2,420                              |
| ML-DSA-65   | 3                       | 4,032                     | 1,952                    | 3,309                              |
| ML-DSA-87   | 5                       | 4,896                     | 2,592                    | 4,627                              |
| ML-KEM-512  | 1                       | 1,632                     | 800                      | 768                                |
| ML-KEM-768  | 3                       | 2,400                     | 1,184                    | 1,088                              |
| ML-KEM-1024 | 5                       | 3,168                     | 1,568                    | 1,568                              |

Díky těmto algoritmům doufáme, že budeme moci používat internet, který zůstane dostatečně bezpečný i v prostředí kvantových počítačů. Relativně větší klíče a podpisy či šifrované texty však zřejmě nevyhnutelně přinesou vyšší výpočetní náročnost.

Jazyk Go má každý z těchto algoritmů efektivně implementovaný, a proto doufám, že budou na vhodných místech aktivně využívány k ochraně vaší bezpečnosti!
