ML-KEM Braid, NIST tarafından standartlaştırılmış ML-KEM'i [1] kullanarak iki tarafın kuantum sonrası güvenli paylaşılan gizlerden oluşan bir dizi üretmesine imkân tanıyan bir Sparse Continuous Key Agreement (SCKA) protokolüdür. Bu paylaşılan gizler, güvenli mesajlaşma için bir Double Ratchet protokolü [2] gibi daha üst düzey protokollere aktarılabilen Forward Secrecy (FS) ve Post-Compromise Security (PCS) özelliklerine sahiptir.
1.1 Sparse Continuous Key Agreement
Klasik Double Ratchet protokolünün merkezindeki ping-pong tarzı anahtar değişimine Continuous Key Agreement (CKA) protokolü denir. Bunun arzu edilen özelliği, her gidiş-dönüşte yeni paylaşılan gizler üretmesi ve bu gizlerin Post-Compromise Security sağlamak üzere Double Ratchet gibi daha üst düzey bir protokole aktarılabilmesidir.
Ancak kuantum güvenli anahtar anlaşması için geçirilmesi gereken iletiler çok daha büyüktür; bu nedenle bant genişliği kısıtları altında bir protokol bu iletileri parçalara bölerek gönderebilir ve her gidiş-dönüşte yeni paylaşılan gizler üretemez. Bunu yakalamak için [3]'ü izliyor ve Sparse Continuous Key Agreement (SCKA) kavramını kullanıyoruz.
Bir SCKA protokolü, sıralı bir paylaşılan gizler dizisi çıkarır ve bu dizideki bir paylaşılan gizin konumu epoch identifier, ya da kısaca epoch, adı verilen işaretsiz bir tamsayıdır. epoch kavramı klasik Double Ratchet protokolünün [2] Diffie-Hellman cırcırında örtük olarak vardır; ancak o bağlamda açık cırcır anahtarı epoch tanımlayıcısı olarak görev yapmak için yeterlidir. Buna karşılık, çıktı anahtarlarını doğru kullandığımızdan emin olmak için epoch'ları boşluksuz biçimde sıkı şekilde sıralayabilme gibi daha güçlü bir özelliğe ihtiyacımız vardır.
Bir SCKA protokolünde her taraf durum tutar ve iki işlev açığa çıkarır:
Send(state) -> (msg, sending_epoch, output_key): Durumu günceller ve msg değerini, yani diğer tarafça işlenecek iletiyi, iletinin alındığı anda diğer tarafın bildiği garanti edilen en son epoch'un tanımlayıcısı olan sending_epoch değerini ve bir epoch tanımlayıcısı ile o epoch için paylaşılan bir gizi içeren, null olabilir bir çift olan output_key değerini döndürür.
Receive(state, msg) -> (receiving_epoch, output_key): Durumu günceller ve diğer tarafın msg üretmek için send() çağırdığında sending_epoch olarak çıkardığı epoch tanımlayıcısı olan receiving_epoch değerini ve bir epoch tanımlayıcısı ile o epoch için paylaşılan bir gizi içeren, null olabilir bir çift olan output_key değerini döndürür.
Kesin doğruluk ve güvenlik tanımları [3]'te verilmiştir. Gayriresmî olarak, doğruluk için protokoldeki iki tarafın üretilen anahtar dizisi üzerinde anlaşması ve sending_epoch ile receiving_epoch değerlerinin doğru biçimde kullanılabilecek en son epoch'ları göstermesi gerekir.
- Oturum anahtarı tutarlılığı: Alice ve Bob sırasıyla (ep, k) ve (ep', k') anahtarlarını çıkarıyorsa ve ep = ep' ise, o zaman k = k' olur.
- Katılımcı başına epoch tekilliği: Her taraf her epoch için en fazla bir anahtar çıkarır.
- Gönderici epoch bilgisi: Send() işlevi sending_epoch döndürdüğünde, gönderici o epoch ve önceki tüm epoch'lara ait anahtara sahiptir veya sahip olmuştur.
- Alıcı epoch bilgisi: Receive() işlevi receiving_epoch döndürdüğünde, alıcı o epoch ve önceki tüm epoch'lara ait anahtara sahiptir veya sahip olmuştur.
- Epoch anlaşması: Send() işlevinden gelen sending_epoch, karşılık gelen Receive() işlevinden gelen receiving_epoch ile eşittir. Özellikle Alice (ya da Bob) msg ve sending_epoch döndüren Send() çağrısı yaparsa, Bob (ya da Alice) Receive(msg) çağrısı yaptığında receiving_epoch = sending_epoch döndürmelidir.
1.2 Artımlı KEM'ler
Learning With Errors varsayımına dayanan bazı kafes tabanlı Key Encapsulation Mechanism (KEM) düzenleri, "gürültülü anahtar değişimi" ile bunu izleyen ve tarafların tam bir paylaşılan gize ulaşmasını sağlayan küçük bir uzlaştırma iletisinden oluşur. Bu nedenle bu KEM'lerin şifreli metinleri iki bölümden oluşur: ct1 olası biçimde sıkıştırılmış bir açık anahtardır ve ct2 bir uzlaştırma iletisidir. Önemli gözlem, ct1'in herhangi bir kapsülleme anahtarı hakkında tam bilgi olmadan da hesaplanabilmesidir.
KEM kullanıcılarının bundan yararlanmasına imkân tanımak için bu KEM'ler aşağıdaki artımlı arayüzü sunabilir:
KeyGen(randomness) -> (dk, ek_header, ek_vector): Rastgele bitler dizisi alır ve bir kapsül açma anahtarı dk, bir alıcının ct1 hesaplaması için gereken tüm bilgileri içeren bir ek_header ve kapsülleme anahtarının "vektör" kısmı olan ek_vector döndürür. Bazı KEM'lerde üstbilginin boş olmasının mümkün olabileceğini not ederiz.
Encaps1(ek_header, randomness) -> (encaps_secret, ct1, shared_secret): Girdi olarak bir kapsülleme anahtarı üstbilgisi ve rastgele bitler dizisi alır ve yeni bir şifreli metnin ilk bölümünü örnekler. Kapsüllemeyi tamamlamak için gereken bilgileri tutan bir kapsülleme gizli değeri encaps_secret, bir şifreli metnin ilk bileşeni ct1 ve şifreli metin tarafından kapsüllenen paylaşılan giz shared_secret döndürür.
Encaps2(encaps_secret, ek_header, ek_vector) -> ct2: Bir kapsülleme gizli değeri, kapsülleme anahtarı üstbilgisi ve kapsülleme anahtarı vektörü alır; kapsülleme sürecini tamamlayarak bir uzlaştırma iletisi ct2 döndürür.
Decaps(dk, ct1, ct2) -> shared_secret: Bir kapsül açma anahtarı ile tam bir şifreli metin alır ve kapsüllenmiş paylaşılan gizli döndürür.
1.2.1 ML-KEM'in Artımlı KEM olarak kullanımı
ML-KEM'in [1] kapsülleme anahtarları, 32 baytlık bir tohumun ardından daha büyük, gürültülü bir vektörden oluşur. Bu tohum, bir şifreli metnin "sıkıştırılmış açık anahtar" bölümü olan ct1'i hesaplamak için gereklidir. ML-KEM tarafından kullanılan Fujisaki-Okamoto dönüşümünün [4] varyantı nedeniyle ct1'i hesaplamak için tam kapsülleme anahtarının SHA3-256 özetini de bilmemiz gerekir. Bu nedenle ML-KEM için kapsülleme anahtarı üstbilgisi şu alanlara sahiptir:
- ek_seed: 32 baytlık bir tohum.
- hek: ek_seed || ek_vector değerinin SHA3-256 özeti.
Bölüm 3.2'de tartışıldığı gibi, ML-KEM'in kapsülleme anahtarı özetini kullanımı, ona standart IND-CCA güvenliğinin ötesine geçen anahtar bağlama özellikleri kazandırır ve herhangi bir alternatif KEM kullanımını değerlendirirken bunun dikkate alınması gerekir.
1.3 Silme Kodlarıyla Parçalama
Bir SCKA protokolü büyük iletileri parçalara bölerek gönderir ve bunu saldırgan bir ağ ortamında dahi sağlam olacak biçimde yapmak zorundadır. Bunu başarmak için bir protokol erasure code veya fountain code kullanabilir. Gayriresmî olarak bu, bir iletiyi parça akışına ayırmak gibi düşünülebilir ve bu belgede bir iletinin "parçası"na yapılan her gönderme, bir silme kodunun bir kod sözcüğüne karşılık gelir.