Go dilinde MLDSA ve MLKEM kullanım kılavuzu
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.
- İmza Oluşturma: Özel anahtar kullanılarak bir mesaj için imza oluşturma.
- İ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:
- strong existential unforgeability: Tek bir imza ve genel anahtar ile başka bir geçerli imza oluşturulamaz.
- chosen message attack: Herhangi bir mesaj için imza ile genel anahtar kullanılarak yeni geçerli bir imza oluşturulamaz.
- 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.
- 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:
- 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.
- 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.
Algoritma | NIST Güvenlik Seviyesi | Özel Anahtar Boyutu | Genel Anahtar Boyutu | İmza/Şifreli Metin 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 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!