Go Dili'nde MLDSA ve MLKEM Kullanım Deneyimi
Genel Bakış
Arka Plan
Kuantum bilgisayarların hızlı hesaplama yetenekleri, uzun süredir mevcut kriptografik sistemlere yönelik bir tehdit olarak algılanmaktadır. Bunun nedeni, mevcut RSA veya ECC gibi sistemlerin kuantum bilgisayarların bu hesaplama kapasitesi nedeniyle çözülme olasılığının bulunmasıdır. Ancak, birkaç yıl önce kuantum bilgisayar kavramının somutlaşmaya başlamasıyla birlikte, buna alternatif çözümler araştırılmaya ve geliştirilmeye başlanmış ve NIST, PQC (Kuantum Dirençli Kriptografi) standardizasyonunu yürütmüştür.
MLDSA ve MLKEM
Nihayetinde NIST, Ağustos 2024'te CRYSTALS-Kyber ve CRYSTALS-Dilithium'a dayalı MLKEM ve MLDSA'yı standart olarak kabul etmiştir. Her iki algoritma da MLWE (Module Learning with Errors) adı verilen bir probleme dayanmaktadır. Bu formata biz kafes tabanlı kriptografi adını veriyoruz.
Kafes tabanlı kriptografi, adından da anlaşılacağı gibi, bir kafes üzerindeki matematiksel problemlerin zorluğuna dayanan bir kriptografi sistemidir. Benim de bu konuda derinlemesine matematiksel bilgim olmamakla birlikte, tek cümleyle özetlenecek olursa, "modül kafesindeki gürültülü doğrusal denklemleri çözme problemi" olarak tanımlanır. Ne kadar zor olduğu tam olarak anlaşılamasa da, bu tür problemlerin kuantum bilgisayarlar tarafından bile çözülemeyecek kadar zor olduğu belirtilmektedir.
MLDSA
Şimdi öncelikle MLDSA'yı inceleyelim.
Yapı
MLDSA, adından da anlaşılacağı gibi, asimetrik bir imza algoritmasıdır ve toplamda aşağıdaki 2 aşamadan geçer:
- İmza Oluşturma: Özel anahtar kullanılarak bir mesaj için imza oluşturulur.
- İmza Doğrulama: Genel anahtar kullanılarak oluşturulan imzanın geçerliliği doğrulanır.
Ayrıca MLDSA'nın aşağıdaki 3 özelliği bulunmaktadır:
- strong existential unforgeability: Bir imza ve genel anahtar ile başka bir geçerli imza oluşturulamaz.
- chosen message attack: Herhangi bir mesaja ait bir imza ile, genel anahtar kullanılarak yeni bir geçerli imza oluşturulamaz.
- side-channel attack: İmza oluşturma sırasında sürekli olarak yeni rastgele değerler ve mesajdan türetilen sözde rastgele değerler kullanıldığı için güvenlik düzeyi yüksektir.
- domain separation: Farklı parametreler için farklı seed'ler kullanarak tekrarlayan güvenlik sorunlarını önler.
Kod
Şimdi basit bir Go dili örnek kodu göstereyim. Bu örnekte cloudflare/circl kütüphanesinin mldsa'sı kullanılmıştır.
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 spesifikasyonu ile anahtarlar oluşturulur.
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şturulur.
22 // Dikkat edilmesi gereken bir nokta, 22 Aralık 2024 itibarıyla mevcut sürümde crypto.Hash(0) dışında bir değer kullanılırsa hata oluşur.
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ı çağrılarak doğrulama yapılır.
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 kısaltılmıştır. Tamamını görmek isterseniz, playground üzerinden çalıştırabilirsiniz.
base64 ile kodlanmış olsa bile 3228 bayt çıkması biraz külfetli olabilir. Yakın gelecekte kuantum bilgisayarlara karşı bu boyuttaki imzaları alıp vermek zorunda kalabileceğimizi düşündüğümüzde biraz endişe verici.
MLKEM
Yapı
MLKEM bir Anahtar Kapsülleme Mekanizması (Key Encapsulation Mechanism)dır. KEM, açık anahtar kriptografi yöntemlerini kullanarak iki taraf arasında paylaşımlı bir anahtar oluşturulmasını sağlayan bir algoritmadır. MLKEM'in anahtar değişim mekanizması aşağıdaki süreçlerden geçer:
- Anahtar Kapsülleme: Gönderici, alıcının açık anahtarını kullanarak şifrelenmiş bir mesaj (cipher text) ve paylaşımlı anahtar (shared key) oluşturur. Bu şifrelenmiş mesaj başlangıçta alıcıya iletilerek kullanılır.
- Anahtar Kapsülleme Çözme: Alıcı, kendi özel anahtarını kullanarak şifrelenmiş mesajdan paylaşımlı anahtarı çıkarır.
MLKEM'de toplam 3 parametre bulunmaktadır. MLKEM-512, MLKEM-768, MLKEM-1024 mevcuttur; daha küçük olanlar daha kısa anahtar ve şifrelenmiş metin üretirken, daha büyük olanlar daha uzun anahtar ve şifrelenmiş metin üretir ve daha yüksek güvenlik seviyesi sunar.
Kod
MLKEM, Go 1.24 sürümünde ekleneceği için, şu anda kullanılabilen Go 1.24rc1 sürümü kullanılmıştır.
1package main
2
3import (
4 "crypto/mlkem"
5 "encoding/base64"
6 "fmt"
7)
8
9func main() {
10 // Alıcının PrivateKey'i oluşturulur.
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 // EncapsulationKey'in Bytes() metodu ve NewEncapsulationKeyX fonksiyonu ile anahtarın çıkarılıp tekrar kullanılabileceğini göstermek amacıyla klonlanmıştır.
20 // Elbette gerçek dünyada kullanıldığında, bu süreç, alıcının metin olarak ifşa edilmiş EncapsulationKey anahtarını göndericinin bir nesneye dönüştürmesi olarak düşünülebilir.
21 clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
22 if err != nil {
23 panic(err)
24 }
25
26 // Gönderici, Encapsulate metodu ile şifrelenmiş metni ve paylaşımlı anahtarı oluşturur.
27 cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()
28
29 // Alıcının özel anahtarını saklayıp çıkarabildiğini göstermek için bilerek klonlanmıştır.
30 clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
31 if err != nil {
32 panic(err)
33 }
34
35 // Alıcı, özel anahtarını kullanarak şifrelenmiş metni Decapsulate ederek başka bir paylaşımlı 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şımlı anahtarların oluşturulduğu görülebilir!
Bu kod playground üzerinden de kontrol edilebilir.
Sonuç
Her algoritmanın spesifikasyonları, güvenlik seviyeleri, özel anahtar, genel anahtar, imza veya şifreleme metninin boyutları aşağıdaki gibi özetlenebilir. Her biri PQC adına yakışır büyüklükte boyutlara sahiptir.
| Algoritma | NIST Güvenlik Seviyesi | Özel Anahtar Boyutu | Genel Anahtar Boyutu | İmza/Şifre Metni Boyutu |
|---|---|---|---|---|
| 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 |
Bu algoritmalar sayesinde kuantum bilgisayarlar üzerinde bile yeterince güvenli bir internet kullanabilmeyi umuyoruz, ancak nispeten büyüyen anahtar ve imza/şifre metni boyutları nedeniyle daha fazla hesaplama yapılmasının kaçınılmaz olduğu görülmektedir.
Yine de Go dili, her algoritmanın etkin bir şekilde uygulanmasını sağladığı için, uygun yerlerde güvenliğinizi korumak amacıyla aktif olarak kullanılmasını umuyoruz!