GoSuda

Използване на MLDSA и MLKEM в езика Go

By snowmerak
views ...

개요

배경

Доста отдавна бързите изчисления на квантовите компютри бяха признати за заплаха за съществуващите криптографски системи. Това е така, защото съществуващите RSA или ECC могат да бъдат дешифрирани поради тази изчислителна мощ на квантовите компютри. Но преди няколко години концепцията за квантов компютър започна да се визуализира и алтернативи започнаха да се проучват и разработват и NIST проведе стандартизация на PQC (Post-Quantum Cryptography).

MLDSA와 MLKEM

В крайна сметка NIST прие MLKEM и MLDSA, базирани на CRYSTALS-Kyber и CRYSTALS-Dilithium, като стандарти през август 2024 г. И двата алгоритъма работят на базата на проблема MLWE (Module Learning with Errors). Ние наричаме този формат криптография, базирана на решетки.

Криптографията, базирана на решетки, както подсказва името, е криптографска система, базирана на трудността на математическите задачи върху решетка. Аз също нямам задълбочени математически познания за това, но ако трябва да го обобщя в един ред, това е проблемът с решаването на линейни уравнения с шум в модулна решетка. Не съм сигурен колко е трудно, но се казва, че този проблем е толкова труден, че не може да бъде решен дори с квантов компютър.

MLDSA

Нека първо да разгледаме MLDSA.

구성

MLDSA, както подсказва името, е алгоритъм за асиметричен подпис и преминава през следните 2 стъпки.

  1. Създаване на подпис: Създаване на подпис за съобщение с помощта на частен ключ
  2. Проверка на подпис: Проверка на валидността на генерирания подпис с помощта на публичен ключ

MLDSA има следните 3 характеристики:

  1. strong existential unforgeability: Невъзможно е да се генерира друг валиден подпис с един подпис и публичен ключ.
  2. chosen message attack: Невъзможно е да се генерира нов валиден подпис с публичен ключ, дори и с подпис за дадено съобщение.
  3. side-channel attack: Сигурността е висока, защото при подписването се използват постоянно нови случайни стойности и псевдослучайни стойности, получени от съобщението.
  4. domain separation: Предотвратява повтарящи се проблеми със сигурността, като гарантира, че различните параметри използват различни seed.

코드

Сега ще ви покажа прост пример за код на Go. Този пример използва mldsa от 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    // Създава ключ със спецификацията mldsa44.
14	pub, priv, err := mldsa44.GenerateKey(rand.Reader)
15	if err != nil {
16		panic(err)
17	}
18
19	message := []byte("Hello, World!")
20
21    // Създава подпис.
22    // Едно нещо, което трябва да се отбележи, е, че възниква грешка, ако не е crypto.Hash(0) въз основа на текущата версия от 22 декември 2024 г.
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    // Извършва проверка чрез извикване на схемата на публичния ключ.
32	ok := pub.Scheme().Verify(pub, message, signature, nil)
33	fmt.Println(ok)
34}
13228 oaSaOA-...
2true

Стойността на подписа е пропусната, защото е твърде дълга. Ако искате да видите пълния текст, опитайте да го изпълните в playground.

Може да е малко обременително, че излизат 3228 байта, въпреки че е кодирано в base64. Малко е обременяващо да мисля, че скоро може да се наложи да даваме и получаваме този размер като подпис срещу квантовите компютри...

MLKEM

구성

MLKEM е механизъм за капсулиране на ключове (Key Encapsulation Mechanism). KEM е алгоритъм, който позволява на две страни да генерират споделен ключ с помощта на криптиране с публичен ключ. Механизмът за обмен на ключове на MLKEM следва следния процес.

  1. Капсулиране на ключ: Изпращачът използва публичния ключ на получателя, за да генерира криптирано съобщение (cipher text) и споделен ключ (shared key). Това криптирано съобщение се предава на получателя първоначално, за да го използва.
  2. Декапсулиране на ключ: Получателят използва своя частен ключ, за да извлече споделения ключ от криптираното съобщение.

Има общо 3 параметъра в MLKEM. Съществуват MLKEM-512, MLKEM-768 и MLKEM-1024, като по-малките дават по-малки ключове и криптиран текст, а по-големите дават по-дълги ключове и криптиран текст и по-високи нива на сигурност.

코드

MLKEM ще бъде добавен в go 1.24, така че използвах go 1.24rc1, който е наличен в момента.

 1package main
 2
 3import (
 4	"crypto/mlkem"
 5	"encoding/base64"
 6	"fmt"
 7)
 8
 9func main() {
10    // Създава PrivateKey на получателя.
11	receiverKey, err := mlkem.GenerateKey1024()
12	if err != nil {
13		panic(err)
14	}
15
16    // MLKEM използва термина EncapsulationKey, а не PublicKey.
17	receiverPubKey := receiverKey.EncapsulationKey()
18
19    // Клонирах го, за да покажа, че ключът може да бъде извлечен и използван отново с Bytes() и NewEncapsulationKeyX на EncapsulationKey.
20    // Разбира се, ако се използва в реалността, можете да го видите като процес, при който подателят създава EncapsulationKey на получателя, който е бил публично достъпен като текст, като обект.
21	clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
22	if err != nil {
23		panic(err)
24	}
25
26    // Encapsulate позволява на подателя да генерира криптиран текст и споделен ключ.
27	cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()
28
29    // Умишлено го клонирах, за да покажа запазването и извличането на частния ключ на получателя.
30	clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
31	if err != nil {
32		panic(err)
33	}
34
35    // Получателят използва частния ключ, за да Decapsulate криптирания текст, за да генерира друг споделен ключ.
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=

В резултат на това можете да видите, че се генерира споделен ключ със същия размер!

Този код може да бъде намерен и в playground.

결론

Спецификациите, нивата на сигурност и размерите на личните ключове, публичните ключове, подписите и шифротекстовете на всеки алгоритъм могат да бъдат обобщени, както следва. Всеки от тях се гордее със значителен размер, както подобава на името PQC.

алгоритъмNIST ниво на сигурностразмер на частен ключразмер на публичен ключразмер на подпис/шифротекст
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

Надяваме се, че с тези алгоритми ще можем да използваме достатъчно сигурен интернет дори на квантови компютри, но изглежда неизбежно, че ще има повече изчисления поради относително увеличените размери на ключовете и подписите/шифротекстовете.

Въпреки това, тъй като всеки алгоритъм е ефективно реализиран на езика Go, надяваме се, че той ще бъде активно използван за защита на вашата сигурност на подходящото място!