Ders 07 / 16
Simetrik ve Asimetrik Şifreleme
Anahtar modellerinin rolleri: asimetrik kurulumda, simetrik taşımada. Kurulum sayısının alışveriş başına düşen gidiş–dönüş maliyeti ve aracının kaybettiği görünürlük.
İçindekiler
Buraya kadar sayılan her karar tek bir varsayıma dayanıyordu: aracı iletiyi okuyabiliyor.
Yöntemi, yolu, kişiye özel imini ve doğrulayıcıyı okuduğu için yinelenebilir,
saklanabilir ve taze kararlarını fazladan bir gidiş–dönüş olmadan alabiliyordu. Bu
varsayımın bir bedeli vardır ve bedeli sessizdir: iletiyi okuyabilen katman, yalnız
kurgudaki aracı değil, yolun üzerindeki her katmandır.
Bu dersin sorusu, iletiyi okunamaz kılan düzeneğin ne olduğu ve bunun kaça mal olduğudur. Ölçü değişmiyor — hâlâ gidiş–dönüş ve karar sayıyoruz. Değişen, ölçülen şeyin artık bir alan değil bir rol olması: hangi anahtar modeli hangi adımda çalışıyor ve o adım kaç tur tutuyor.
İki Anahtar Modeli
Simetrik şifreleme (symmetric encryption) tek bir sır kullanır. Aynı sır iki tarafta bulunur; gönderen onunla gövdeyi kapatır, alan aynı sırla açar. Maliyeti gövdenin uzunluğuyla ölçeklenir ve tur maliyeti yoktur — sır zaten iki taraftadır. Tek sorusu şudur: sır iki tarafa nasıl geldi?
Bu soru küçük görünür ama tek başına simetrik modeli bir ağ protokolü için yetersiz kılar. Sır önceden elden verilmek zorundaysa, birbiriyle konuşmak isteyen her uç çiftinin ayrı bir sırra ihtiyacı olur ve gereken sır sayısı uç sayısıyla değil uç çifti sayısıyla büyür. Dahası, hiç karşılaşmamış iki uç hiçbir zaman konuşamaz. Ağın tanımı gereği uçlar birbirini önceden tanımaz; taşıma güvenliğinin çözmesi gereken ilk sorun budur.
Asimetrik şifreleme (asymmetric encryption) bir çift kullanır. Açık anahtar (public key) dağıtılır, gizli anahtar (private key) hiç gönderilmez. Çiftin işe yaraması şuradan gelir: bir taraf kendi gizlisiyle karşının açık değerini birleştirdiğinde, karşı taraf da kendi gizlisiyle onun açık değerini birleştirdiğinde aynı sayı çıkar. Bu sayı hiçbir zaman yolda taşınmaz; iki uçta ayrı ayrı üretilir. Bu adıma anahtar değişimi (key exchange), çıkan sayıya ortak sır (shared secret) denir.
Kimlik, Erişim ve Kriptografi kursu bu iki modelin güvenlik özelliklerini kurdu: hangi varsayım altında neyin kırılamaz sayıldığını, imzanın neyi kanıtladığını, anahtar uzunluğunun ne anlama geldiğini. O kuram burada tekrarlanmıyor. Fark tek cümlede durur: orada güvenlik özelliği ölçüldü, burada tur ve karar ölçülüyor.
Rollerin Sırası
İki model rakip değildir; sırayla çalışır.
kurulum — asimetrik roller 1. istemci -> sunucu : istemcinin açık değeri 2. sunucu -> istemci : sunucunun açık değeri 3. iki taraf da ortak sırra kendi başına varır (yolda hiçbir şey taşınmaz) taşıma — simetrik rol 4. istemci -> sunucu : ortak sırla kapatılmış gövde 5. sunucu -> istemci : ortak sırla kapatılmış gövde 6. 4-5 istenildiği kadar yinelenir; 1-3 yinelenmez
Bu döküm bir belirtim özeti değil, rollerin sırasıdır ve çalıştırılmaz. Dikkat edilecek satır altıncısıdır: kurulum bir kez, taşıma çok kez.
Ders İçinde Modellenmiş Düzenek
Aşağıdaki düzenek ders içinde modellenmiştir. Gerçek bir anahtar değişimi değildir, gerçek bir şifre değildir ve hiçbir güvenlik özelliği taşımaz: modülüs küçültülmüştür, gizli sayılar dardır, simetrik dönüşüm bir oyuncaktır. Modellenen tek şey ortaklığın nasıl doğduğu ve hangi işin hangi adımda yapıldığıdır.
TOHUM = 20260809 ASAL = 2147483647 # ders içinde küçültülmüş modülüs TABAN = 5 def uretec(tohum: int): d = tohum % 2147483646 + 1 def r(n: int) -> int: nonlocal d d = (d * 48271) % ASAL return d % n return r def acik_deger(gizli: int) -> int: return pow(TABAN, gizli, ASAL) def ortak_sir(kendi_gizli: int, karsi_acik: int) -> int: return pow(karsi_acik, kendi_gizli, ASAL) def simetrik(veri: bytes, sir: int) -> bytes: r = uretec(sir) return bytes(b ^ r(251) for b in veri) r = uretec(TOHUM) iletiler = [bytes(r(251) for _ in range(180 + r(441))) for _ in range(40)] istemci_gizli, sunucu_gizli = 1 + r(9973), 1 + r(9973) istemci_sir = ortak_sir(istemci_gizli, acik_deger(sunucu_gizli)) sunucu_sir = ortak_sir(sunucu_gizli, acik_deger(istemci_gizli)) tasinan = [simetrik(i, istemci_sir) for i in iletiler] cozulen = [simetrik(t, sunucu_sir) for t in tasinan] print(f"ortak sır aynı: {istemci_sir == sunucu_sir}") print(f"ileti {len(iletiler)}, gövde {sum(len(i) for i in iletiler)} bayt") print(f"taşınan {sum(len(t) for t in tasinan)} bayt, çözülen özdeş: {cozulen == iletiler}")
ortak sır aynı: True ileti 40, gövde 15767 bayt taşınan 15767 bayt, çözülen özdeş: True
İki taraf da yalnız kendi gizlisini ve karşının açık değerini kullandı; gizliler hiç gönderilmedi ve iki taraf aynı sayıya vardı. Gövde o sayıdan türetilen bir diziyle katlandı; aynı dizi ikinci kez uygulandığında gövde geri geldi. Taşınan bayt sayısının gövdeyle aynı kalması da tesadüf değil: simetrik rol veriyi uzatmaz, yalnız okunamaz kılar.
Gerçek bir taşımada bu düzeneğin her parçası daha ağırdır: modülüs çok daha büyük seçilir, gizli sayılar çok daha geniş bir aralıktan çekilir, simetrik dönüşüm gövdeyi kapatmakla kalmayıp değiştirilip değiştirilmediğini de bildirir. Bu seçimlerin gerekçesi Kimlik, Erişim ve Kriptografi kursunun konusudur. Burada modelden alınan tek şey iş bölümüdür.
Kurulum Bir Kez, Taşıma Çok Kez
Kırk alışverişin tamamı aynı düzenekten geçirilirse, değişen tek şey kaç kez kurulum yapıldığıdır. Aşağıdaki ölçüm bunu üç rejimde sayıyor: her iletiye bir kurulum, sekiz bağlantıya bölünmüş kurulum, tek kalıcı bağlantı.
Ölçümün varsayımları:
- GT1 — Şifrelemenin kendisi ders içinde modellenmiştir: modülüs küçültülmüş, gizli sayılar dar bir aralıktan çekilmiş, simetrik dönüşüm bir katlamadır. Gerçek bir algoritma çalıştırılmaz ve düzenek hiçbir güvenlik özelliği taşımaz.
- GT2 — Gövde tek bir tohumdan üretilir: kırk ileti, her biri 180 ile 620 bayt arasında. Aynı gövde üç rejimde de kullanılır.
- GT3 — Bir kurulum bir gidiş–dönüş sayılır; her kurulumda iki taraf yeni birer gizli çeker ve iki açık değer üretilir.
- GT4 — Üç rejim karşılaştırılır: her iletide kurulum, sekiz bağlantı, tek kalıcı bağlantı. Bağlantı başına bir kurulum yapılır ve o kurulumdan çıkan sır, bağlantının bütün alışverişlerini kapsar.
- GT5 — Kırk alışverişlik kümede ölçülebilen en küçük tur farkı bir kurulumdur, yani 1/40 = 0,025; bundan küçük bir kazanç bu kümeyle savunulamaz.
- GT6 — Rol maliyeti süreyle değil işlem sayısıyla ölçülür: üs alma kare-al-ve-çarp biçiminde açılıp modüler çarpmalar, simetrik dönüşümde katlamalar sayılır. Bu derste sayılan şey turdur; aracının karar tablosu ölçüme girmez.
TOHUM = 20260809 ASAL = 2147483647 TABAN = 5 SAYAC = {"acik_deger": 0} def uretec(tohum: int): d = tohum % 2147483646 + 1 def r(n: int) -> int: nonlocal d d = (d * 48271) % ASAL return d % n return r def acik_deger(gizli: int) -> int: SAYAC["acik_deger"] += 1 return pow(TABAN, gizli, ASAL) def kurulum(rk) -> int: istemci_gizli, sunucu_gizli = 1 + rk(9973), 1 + rk(9973) acik_deger(istemci_gizli) # sunucuya giden değer return pow(acik_deger(sunucu_gizli), istemci_gizli, ASAL) def simetrik(veri: bytes, sir: int) -> bytes: r = uretec(sir) return bytes(b ^ r(251) for b in veri) r = uretec(TOHUM) iletiler = [bytes(r(251) for _ in range(180 + r(441))) for _ in range(40)] print(f"{'rejim':<22s} {'kurulum':>8s} {'açık değer':>11s} {'simetrik bayt':>14s} " f"{'alışveriş başına tur':>21s} {'sır başına alışveriş':>21s}") for ad, baglanti in (("her iletide kurulum", 40), ("sekiz bağlantı", 8), ("tek kalıcı bağlantı", 1)): SAYAC["acik_deger"] = 0 rk, bayt = uretec(TOHUM + 1), 0 sirlar = [kurulum(rk) for _ in range(baglanti)] for sira, ileti in enumerate(iletiler): bayt += len(simetrik(ileti, sirlar[sira % baglanti])) print(f"{ad:<22s} {baglanti:8d} {SAYAC['acik_deger']:11d} {bayt:14d} " f"{baglanti / len(iletiler):21.3f} {len(iletiler) / baglanti:21.1f}")
rejim kurulum açık değer simetrik bayt alışveriş başına tur sır başına alışveriş her iletide kurulum 40 80 15767 1.000 1.0 sekiz bağlantı 8 16 15767 0.200 5.0 tek kalıcı bağlantı 1 2 15767 0.025 40.0
Üç satır arasında simetrik bayt değişmiyor: gövde her rejimde aynı, 15767 bayt. Değişen tek şey kurulum sayısı ve onun doğurduğu turdur. Her iletide kurulum yapan rejimde alışveriş başına 1,000 ek gidiş–dönüş düşer — her ileti kendi kurulumunu öder. Sekiz bağlantıda bu 0,200, tek kalıcı bağlantıda 0,025 olur.
Kırk kat fark tek bir tasarım kararından gelir. Asimetrik rolün maliyeti gövdeyle değil kurulum sayısıyla ölçeklenir; simetrik rolün maliyeti kurulum sayısıyla değil gövdeyle ölçeklenir. İki modelin neden birlikte kullanıldığının tamamı budur: pahalı olan seyrek çalışır, ucuz olan sık.
Bu kümenin çözünürlüğü de burada okunur. Kırk alışverişlik bir kümede ölçülebilen en küçük tur farkı bir kurulumdur, yani 1/40 = 0,025. Bundan küçük bir kazanç iddia edilemez.
Son sütun bedava olmadığını gösteriyor. Kurulum seyrekleştikçe bir sırra bağlanan alışveriş sayısı artar: her iletide kurulumda bir sır bir alışverişi kapsar, sekiz bağlantıda beşini, tek kalıcı bağlantıda kırkını birden. Tur kazancı ile yalıtım aynı kolu çekiyor ve ters yönlere gidiyor. Kurulumun her yinelenişinde iki tarafın yeni birer gizli çekmesi de bu yüzden anlamlıdır: yeni gizli, kapsamı yeniden bir bağlantıyla sınırlar. Gizliyi yinelemek — aynı gizliyi bütün kurulumlarda kullanmak — tabloda hiçbir turu kazandırmaz ama son sütunu sessizce kırka çıkarır.
Neden Taşıma Simetriktir
Rollerin sırası bir alışkanlık değil, bir hesabın sonucudur. Modellenmiş düzenekte iki işin maliyeti aynı birimle sayılabilir: asimetrik rol modüler çarpma yapar, simetrik rol katlama. Üs alma işlemini kare-al-ve-çarp biçiminde açıp her çarpmayı saymak, sıranın nereden geldiğini gösterir. Aynı gövde iki rolle de taşınır ve ikisi de geri açılır.
TOHUM = 20260809 ASAL = 2147483647 TABAN = 5 ACIK_US = 1223 GIZLI_US = pow(ACIK_US, -1, ASAL - 1) def uretec(tohum: int): d = tohum % 2147483646 + 1 def r(n: int) -> int: nonlocal d d = (d * 48271) % ASAL return d % n return r def us_al(taban: int, us: int, sayac: list[int]) -> int: """Kare-al-ve-çarp: her modüler çarpma sayaca düşer.""" sonuc, t = 1, taban % ASAL while us > 0: if us % 2 == 1: sonuc = (sonuc * t) % ASAL sayac[0] += 1 t = (t * t) % ASAL sayac[0] += 1 us //= 2 return sonuc def katla(veri: bytes, sir: int, sayac: list[int]) -> bytes: r = uretec(sir) sayac[0] += len(veri) return bytes(b ^ r(251) for b in veri) r = uretec(TOHUM) govde = b"".join(bytes(r(251) for _ in range(180 + r(441))) for _ in range(40)) kurulum = [0] istemci_gizli, sunucu_gizli = 1 + r(9973), 1 + r(9973) sunucu_acik = us_al(TABAN, sunucu_gizli, kurulum) us_al(TABAN, istemci_gizli, kurulum) sir = us_al(sunucu_acik, istemci_gizli, kurulum) asimetrik = [0] kapali = [us_al(b, ACIK_US, asimetrik) for b in govde] acilan = bytes(us_al(x, GIZLI_US, asimetrik) for x in kapali) simetrik = [0] s_acilan = katla(katla(govde, sir, simetrik), sir, simetrik) print(f"{'iş':<34s} {'modüler çarpma':>15s} {'katlama':>9s}") print(f"{'kurulum (üç üs alma)':<34s} {kurulum[0]:15d} {0:9d}") print(f"{'gövdeyi asimetrik taşımak':<34s} {asimetrik[0]:15d} {0:9d}") print(f"{'gövdeyi simetrik taşımak':<34s} {0:15d} {simetrik[0]:9d}") print() print(f"gövde {len(govde)} bayt, asimetrik geri geldi: {acilan == govde}, " f"simetrik geri geldi: {s_acilan == govde}") print(f"asimetrik taşıma kuruluma göre {asimetrik[0] / kurulum[0]:.0f} kat")
iş modüler çarpma katlama kurulum (üç üs alma) 54 0 gövdeyi asimetrik taşımak 930253 0 gövdeyi simetrik taşımak 0 31534 gövde 15767 bayt, asimetrik geri geldi: True, simetrik geri geldi: True asimetrik taşıma kuruluma göre 17227 kat
Kurulum üç üs alma tutar ve toplam 54 modüler çarpma yapar. Gövde ne kadar büyürse büyüsün bu sayı değişmez, çünkü asimetrik rol gövdeye değil sabit boyutlu bir sayıya dokunur. Aynı gövdeyi baştan sona asimetrik rolle taşımak 930253 modüler çarpma tutar: kurulumun 17227 katı. Simetrik rol aynı işi 31534 katlamayla bitirir ve tek bir modüler çarpma yapmaz.
Önemli olan sayıların büyüklüğü değil, neye bağlı oldukları. Kurulumun maliyeti gövdeden bağımsızdır; asimetrik taşımanın maliyeti gövdeyle doğrusal büyür ve her baytı pahalı bir işlemden geçirir; simetrik taşımanın maliyeti de gövdeyle doğrusal büyür ama bayt başına yaptığı iş ucuzdur. Rollerin sırası bu üç eğrinin karşılaştırmasından çıkar: pahalı olan sabit kalabildiği yerde, ucuz olan büyüyebildiği yerde çalışır.
Bir ayrıntı daha vardır. Kurulumdan çıkan ortak sır gövdeye doğrudan uygulanmaz; ondan türetilen ayrı bir oturum anahtarı (session key) kullanılır ve genellikle her yön için ayrı bir anahtar türetilir. Türetme yerel bir işlemdir, ileti göndermez, tur eklemez. Kazandırdığı şey iki yönün ve iki oturumun birbirinden ayrılmasıdır. Tur bütçesi açısından sonuç şudur: türetilen anahtar sayısı artsa bile kurulumun turu sabit kalır.
Aracının Gördüğü ve Görmediği
Gövde kapandığında aracı gövdeden karar alamaz. Bu dersin modellediği dönüşüm yalnız gövdeyi kapattı; sonraki iki dersin konusu olan taşıma zarfı (transport envelope) başlık alanlarını da içine alır ve aracının okuyabildiği kümeyi daha da daraltır. O daraltmanın karar tablosuna ne yaptığı el sıkışma dersinde sayılacak. Burada sayılan yalnız turdur.
Kapalı bir taşımada aracının hâlâ gördüğü şeyler vardır ve her birinin bir daraltması bulunur:
- Konak adı. Aracı iletiyi doğru sunucuya yönlendirebilmek için bir ada ihtiyaç duyar. Daraltma: ad da zarfa alınırsa aracı yönlendiremez; bu bir kayıp değil takastır — karar aracıdan alınır, uca verilir.
- İleti uzunluğu. Simetrik rol veriyi uzatmadığı için taşınan bayt, gövdenin baytıdır. Daraltma: gövdeye dolgu eklenirse uzunluk kaba bir bant hâline gelir ve ayırt ediciliği düşer.
- Tur deseni. Kaç ileti, hangi aralıkla gidiyor. Daraltma: alışverişler tek bir kalıcı bağlantıda birleştirilirse desen bir bağlantının içine gömülür.
- Hedef adres ve bağlantı noktası. Taşıma katmanının başlıkları kapanan gövdenin dışında kalır; aracı iletiyi iletebilmek için onları okumak zorundadır. Daraltma: aynı adres arkasında çok sayıda uç toplanırsa adres tek bir ucu değil bir kümeyi gösterir ve ayırt ediciliği düşer.
Bir de yapılandırma kusuru olarak okunması gereken bir seçim vardır: kurulum turunu tamamen atlayıp ortak sırrı önceden paylaşılmış sabit bir değere bağlamak. Kazanç açıktır — tabloda 0,025’lik satır bile ortadan kalkar. Yanlış olan şudur: her oturum aynı sırra bağlanır, oturumlar birbirinden ayrılamaz ve sırrın tek bir kez elden çıkması geçmiş alışverişleri de kapsar. Bu dersin söylediği, neyin yanlış olduğudur; bunun nasıl kullanılacağı bu kursun konusu değildir.
Özet
- Simetrik model tek sır kullanır ve maliyeti gövdeyle ölçeklenir; asimetrik model bir çift kullanır ve maliyeti kurulum sayısıyla ölçeklenir.
- Anahtar değişimi, iki tarafın kendi gizlisini göndermeden aynı ortak sırra varmasıdır; ortak sır yolda hiç taşınmaz.
- Ders içinde modellenmiş düzenekte iki taraf aynı sayıya vardı ve 15767 baytlık gövde dönüşümden geçip özdeş olarak geri geldi; düzenek güvenlik özelliği taşımaz.
- Kırk alışverişte alışveriş başına ek gidiş–dönüş, her iletide kurulumda 1,000; sekiz bağlantıda 0,200; tek kalıcı bağlantıda 0,025 çıkar — simetrik bayt üçünde de aynıdır.
- Kapalı taşımada aracının gördüğü konak adı, ileti uzunluğu ve tur deseninin her birinin bir daraltması vardır; ortak sırrı sabit bir değere bağlamak ise bir yapılandırma kusurudur.
Sonraki Adım
Kurulum bir sayı üretti ve iki taraf o sayıda anlaştı. Ama anlaşılan şey sırdır, kimlik değildir: ortak sır, karşı ucun kim olduğu hakkında hiçbir şey söylemez. Açık değeri gönderen taraf ölçüm istasyonu da olabilir, o adı kullanan başka bir uç da. İstemcinin elindeki tek dayanak yine iletide yazandır — ve iletide yazanı doğrulayan hiçbir şey yoktur. Sonraki ders, bir adın bir açık anahtara nasıl bağlandığını ve istemcinin bu bağı doğrularken kaç kez soru sorduğunu ölçecek.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.