GoSuda

Go dilinde MLDSA ve MLKEM kullanım kılavuzu

By snowmerak
views ...

Genel Bakış

Arka Plan

Kuantum bilgisayarların hızlı hesaplama gücü, uzun zamandır mevcut şifreleme sistemleri için bir tehdit olarak kabul edilmektedir. Mevcut RSA veya ECC gibi sistemler, kuantum bilgisayarların bu hesaplama yetenekleri nedeniyle deşifre edilebilir hale gelebilir. Ancak, kuantum bilgisayar kavramının somutlaşmaya başlamasıyla birlikte, birkaç yıl önce bu duruma yönelik alternatifler araştırılıp geliştirilmeye başlandı ve NIST, PQC (Kuantum Dirençli Şifreleme) standardizasyonunu yürütmektedir.

MLDSA ve MLKEM

Nihayetinde NIST, 2024 Ağustos ayında CRYSTALS-Kyber ve CRYSTALS-Dilithium tabanlı MLKEM ve MLDSA'yı standart olarak kabul etmiştir. Her iki algoritma da MLWE (Module Learning with Errors) problemi temelinde çalışmaktadır. Bu formata kafes tabanlı şifreleme diyoruz.

Kafes tabanlı şifreleme, adından da anlaşılacağı üzere, bir kafes üzerindeki matematiksel problemlerin zorluğuna dayanan bir şifreleme sistemidir. Benim de bu konuda derinlemesine matematiksel bilgim olmamasına rağmen, tek bir cümleyle özetlersek modüler kafeste gürültülü doğrusal denklemleri çözme problemi diyebiliriz. Ne kadar zor olduğu anlaşılmıyor ama bu tür problemlerin kuantum bilgisayarlar tarafından bile çözülemeyecek kadar zor olduğu söyleniyor.

MLDSA

Şimdi öncelikle MLDSA hakkında bilgi edinelim.

Yapı

MLDSA, adından da anlaşılacağı gibi asimetrik bir imza algoritmasıdır ve toplamda aşağıdaki 2 aşamadan geçer.

  1. İmza Oluşturma: Özel anahtar kullanılarak bir mesaj için imza oluşturma.
  2. İmza Doğrulama: Oluşturulan imzanın geçerliliğini kontrol etmek için genel anahtar kullanma.

Ayrıca MLDSA'nın aşağıdaki 4 özelliği vardır:

  1. strong existential unforgeability: Tek bir imza ve genel anahtar ile başka bir geçerli imza oluşturulamaz.
  2. chosen message attack: Herhangi bir mesaj için imza ile genel anahtar kullanılarak yeni geçerli bir imza oluşturulamaz.
  3. side-channel attack: İmzalama sırasında sürekli olarak yeni rastgele değerler ve mesajdan türetilmiş sözde rastgele değerler kullanılarak yüksek güvenlik sağlanır.
  4. domain separation: Farklı parametreler için farklı tohumlar kullanılarak tekrarlayan güvenlik sorunları önlenir.

Kod

Şimdi size basit bir Go dili örnek kodu göstereceğim.
Bu örnekte cloudflare/circl'ın mldsa'sını kullandım.

 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 spesifikasyonunda anahtar oluşturur.
14	pub, priv, err := mldsa44.GenerateKey(rand.Reader)
15	if err != nil {
16		panic(err)
17	}
18
19	message := []byte("Hello, World!")
20
21    // İmza oluşturur.
22    // Dikkat edilmesi gereken bir nokta, 22 Aralık 2024 itibariyle mevcut sürüme göre crypto.Hash(0) değilse hata oluşmasıdır.
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    // Genel anahtarın şemasını çağırarak doğrulamayı yapar.
32	ok := pub.Scheme().Verify(pub, message, signature, nil)
33	fmt.Println(ok)
34}
13228 oaSaOA-...
2true

İmza değeri çok uzun olduğu için atlandı. Tamamını görmek isterseniz, playground üzerinde çalıştırın.

Base64 ile kodlanmış olsa bile 3228 bayt olması biraz zorlayıcı olabilir.
Yakın zamanda kuantum bilgisayarlara karşı bir imza olarak bu boyutta veri alışverişi yapmamız gerekebileceğini düşünmek biraz rahatsız edici...

MLKEM

Yapı

MLKEM, bir anahtar kapsülleme mekanizmasıdır (Key Encapsulation Mechanism). KEM, iki taraf arasında paylaşılan bir anahtar oluşturmak için genel anahtar şifrelemesini kullanan bir algoritmadır. MLKEM'in anahtar değişim mekanizması aşağıdaki süreçten geçer:

  1. Anahtar Kapsülleme: Gönderen, alıcının genel anahtarını kullanarak şifrelenmiş bir mesaj (cipher text) ve paylaşılan bir anahtar (shared key) oluşturur. Bu şifrelenmiş mesajı başlangıçta alıcıya ileterek kullanmasını sağlar.
  2. Anahtar Kapsül Açma: Alıcı, özel anahtarını kullanarak şifrelenmiş mesajdan paylaşılan anahtarı çıkarır.

MLKEM'de toplam 3 parametre bulunmaktadır. MLKEM-512, MLKEM-768 ve MLKEM-1024 mevcuttur ve ne kadar küçük olursa, anahtar ve şifrelenmiş metin o kadar küçük olur ve ne kadar büyük olursa, anahtar ve şifrelenmiş metin o kadar uzun olur ve güvenlik seviyesi daha yüksek olur.

Kod

MLKEM, go 1.24'e ekleneceği için şu an için kullanabileceğimiz go 1.24rc1'i kullandık.

 1package main
 2
 3import (
 4	"crypto/mlkem"
 5	"encoding/base64"
 6	"fmt"
 7)
 8
 9func main() {
10    // Alıcının PrivateKey'ini oluşturur.
11	receiverKey, err := mlkem.GenerateKey1024()
12	if err != nil {
13		panic(err)
14	}
15
16    // MLKEM'de PublicKey yerine EncapsulationKey terimi kullanılır.
17	receiverPubKey := receiverKey.EncapsulationKey()
18
19    // Basitçe EncapsulationKey'in Bytes() ve NewEncapsulationKeyX ile anahtarın çıkarılıp tekrar kullanılabileceğini göstermek için klonladım.
20    // Elbette gerçek hayatta kullanıldığında bu işlem, metin olarak yayınlanmış alıcının EncapsulationKey anahtarını gönderenin bir nesne haline getirme süreci olarak düşünülebilir.
21	clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
22	if err != nil {
23		panic(err)
24	}
25
26    // Encapsulate ile gönderen şifreli metin ve paylaşılan anahtar oluşturur.
27	cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()
28
29    // Alıcının özel anahtarını kaydedip çıkarmayı göstermek için bilerek klonladım.
30	clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
31	if err != nil {
32		panic(err)
33	}
34
35    // Alıcı, özel anahtarını kullanarak şifreli metni Decapsulate ederek başka bir paylaşılan anahtar oluşturur.
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=

Sonuç olarak aynı boyutta paylaşılan anahtarın oluşturulduğunu görebilirsiniz!

Bu kodu playground üzerinde de kontrol edebilirsiniz.

Sonuç

Her bir algoritmanın özellikleri, güvenlik seviyesi veya özel anahtar, genel anahtar, imza veya şifreli metin boyutu aşağıdaki gibi özetlenebilir. Her biri PQC adına yakışır şekilde büyük boyutlara sahiptir.

AlgoritmaNIST Güvenlik SeviyesiÖzel Anahtar BoyutuGenel Anahtar Boyutuİmza/Şifreli Metin Boyutu
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

Bu algoritmalar sayesinde kuantum bilgisayarlarda bile yeterince güvenli bir internet kullanabileceğimizi umuyoruz, ancak nispeten büyüyen anahtar ve imza/şifreli metin boyutları nedeniyle daha fazla hesaplama olacağı kaçınılmaz görünüyor.

Yine de, Go dili her algoritmayı etkili bir şekilde uyguladığı için, uygun yerlerde güvenliğinizi korumak için aktif olarak kullanılmasını umuyoruz!