İçeriğe geç
academia.sh

Ders 01 / 21

Karma, Şifreleme ve Kodlama

Üç işlemin geri döndürülebilirlik cinsinden ayrılması: aynı sayaç okumasının kodlanmış, şifrelenmiş ve karmalanmış hâli, geri dönüş için gereken gizli kalem sayısının sırasıyla 0, 2 ve hiç olması, dört alan ile üç işlemin on iki eşleşmesinden yalnız dördünün uygun çıkması ve yanlış eşleşmenin 24.800 kaydın geri dönüşünü yok etmesi.

İçindekiler

Önceki kurs ağ üzerindeki iddiaları saydı ve yirmi derste hep aynı yere vardı: bir iddia ancak kanıtlanabildiği ölçüde kabul edilir. Kapanışta kalan soru, kanıtın kendisiyle ilgiliydi — o kanıt neye dayanıyor, anahtar kimde duruyor, güven tam olarak nereden başlıyor? Bu kurs o başlangıç noktasını adlandırır ve kırıldığında ne düştüğünü sayar.

Adlandırmadan önce bir ayrım gerekir. Kurgu bölgesel ölçüm ağında bir sayaç okuması sahadan merkeze giderken üç ayrı işlemden geçer ve üçü de çıktıyı okunamaz hâle getirir. Bir kayıt görüntüsüne bakan biri için üçü de aynı görünür: anlamsız harf ve rakam dizisi. Oysa üçünün güvenlik değeri birbirinden bağımsızdır ve aralarındaki fark tek bir soruyla ölçülür — bu çıktıdan girdiye dönmek için elde kaç gizli kalem olması gerekiyor?

Üç İşlem, Üç Ayrı Soru

KT1: kodlama (encoding) bir gösterim değişikliğidir; verinin baytlarını başka bir alfabede yazar ve geri dönüş için hiçbir gizli kalem gerekmez. Amacı taşınabilirliktir: bir baytın aktarım yolunda bozulmadan geçmesi.

KT2: şifreleme (encryption) geri döndürülebilir bir dönüşümdür; geri dönüş, sayılabilir sayıda gizli kaleme bağlıdır. Amacı gizliliktir: kaleme sahip olmayan tarafın içeriği öğrenememesi.

KT3: karma (hashing) tek yönlü bir özetlemedir; çıktıdan girdiye dönmek için hiçbir kalem yetmez, çünkü tersi tanımlı bir işlem yoktur. Amacı bütünlük ve karşılaştırmadır: iki verinin aynı olup olmadığının, verinin kendisi elde tutulmadan sınanması.

Bu üç cümlenin ortak yanı, hiçbirinde “güçlü” ya da “güvenli” sözcüğünün geçmemesidir. Üçü de sayılabilir bir şey söylüyor: geri dönüş için gereken kalem sayısı sırasıyla sıfır, birden fazla ve hiç.

Aynı Girdi Üç İşlemden Geçiyor

Aşağıdaki birim kurgu bir sayaç okumasını üç işlemden geçirir. Anahtar, çıktı koşumdan koşuma aynı kalsın diye sabit bir tohumdan türetilmiştir; gerçek bir anahtar değildir ve gerçek bir kurulumda anahtar bu biçimde üretilmez.

// kripto/uclu.mjs — ayni girdiyi uc islemden gecirip geri donduruleblirligi olcer:
// kodlama (base64), sifreleme (AES-256-GCM), karma (SHA-256). Girdi, kurgu bolgesel
// olcum agindan bir sayac okumasidir. Gercek anahtar yok; anahtar sabit bir tohumdan
// turetilir ki cikti kosumdan kosuma ayni kalsin. Rastgelelik yok.
import { createHash, createCipheriv, createDecipheriv, scryptSync } from "node:crypto";

// KT1: kodlama bir gosterim degisikligidir; geri donus icin gizli kalem gerekmez.
// KT2: sifreleme geri donduruleblir bir donusumdur; geri donus tam olarak sayilabilir
//      sayida gizli kaleme baglidir.
// KT3: karma tek yonlu bir ozetlemedir; hicbir kalem geri donusu vermez.

export const OKUMA = "SAY-4417|2026-03-01T06:00Z|41982";
export const UZUN  = OKUMA + "|SAY-4418|2026-03-01T06:00Z|8813304";
const ANAHTAR = scryptSync("kurgu-tohum", "kurgu-tuz", 32, { N: 2 ** 12, r: 8, p: 1 });
const NONCE = Buffer.alloc(12, 7);                    // kurgu, sabit

export const kodla   = (m) => Buffer.from(m).toString("base64");
export const karmala = (m) => createHash("sha256").update(m).digest("base64");
export function sifrele(m) {
  const s = createCipheriv("aes-256-gcm", ANAHTAR, NONCE);
  const g = Buffer.concat([s.update(m, "utf8"), s.final()]);
  return Buffer.concat([g, s.getAuthTag()]).toString("base64");
}
export function coz(g64, anahtar = ANAHTAR) {
  const t = Buffer.from(g64, "base64");
  const c = createDecipheriv("aes-256-gcm", anahtar, NONCE);
  c.setAuthTag(t.subarray(t.length - 16));
  return Buffer.concat([c.update(t.subarray(0, t.length - 16)), c.final()]).toString();
}
export const denesin = (f) => { try { return f() === OKUMA ? "evet" : "hayir"; }
                                catch { return "hayir"; } };
export const YANLIS = scryptSync("baska-tohum", "kurgu-tuz", 32, { N: 2 ** 12, r: 8, p: 1 });
// kripto/olc.mjs — uc islemin cikti bicimi, belirlenimciligi ve geri donusu.
import { OKUMA, UZUN, kodla, karmala, sifrele, coz, denesin, YANLIS } from "./uclu.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const A = [-11, 7, 7, 14, 14];
yaz(A, "islem", "kisa", "uzun", "belirlenimci", "gizli kalem");
for (const [ad, f, kalem] of [["kodlama", kodla, 0], ["sifreleme", sifrele, 2],
                              ["karma", karmala, "-"]])
  yaz(A, ad, f(OKUMA).length, f(UZUN).length,
      f(OKUMA) === f(OKUMA) ? "evet" : "hayir", kalem);

console.log("\ngeri donus gercekten denendi (girdiyi aynen geri verdi mi):");
const B = [-32, 6];
for (const [ad, f] of [
  ["kodlama, elde hicbir kalem yok", () => Buffer.from(kodla(OKUMA), "base64").toString()],
  ["sifreleme, dogru anahtarla", () => coz(sifrele(OKUMA))],
  ["sifreleme, yanlis anahtarla", () => coz(sifrele(OKUMA), YANLIS)],
  ["sifreleme, tek bayti degismis", () => {
    const b = Buffer.from(sifrele(OKUMA), "base64"); b[3] ^= 1;
    return coz(b.toString("base64")); }],
]) yaz(B, ad, denesin(f));
yaz(B, "karma, ters islev yok", "hayir");

console.log("\nayni girdinin uc cikti bicimi:");
console.log("  kodlama  :", kodla(OKUMA));
console.log("  sifreleme:", sifrele(OKUMA));
console.log("  karma    :", karmala(OKUMA));
islem         kisa   uzun  belirlenimci   gizli kalem
kodlama         44     92          evet             0
sifreleme       64    112          evet             2
karma           44     44          evet             -

geri donus gercekten denendi (girdiyi aynen geri verdi mi):
kodlama, elde hicbir kalem yok    evet
sifreleme, dogru anahtarla        evet
sifreleme, yanlis anahtarla      hayir
sifreleme, tek bayti degismis    hayir
karma, ters islev yok            hayir

ayni girdinin uc cikti bicimi:
  kodlama  : U0FZLTQ0MTd8MjAyNi0wMy0wMVQwNjowMFp8NDE5ODI=
  sifreleme: KtcWlbMqgsctrQ9mH5TfZXklUgBZe3RQghkBaCASMIF/zJIXfxBHDQ8B0sIX7nzA
  karma    : 6MaKWYn3eYX57Bdf2685XV76MBSSJCOE1SLYc6Rz7zg=

Ölçülen Şey: Geri Dönüş İçin Gereken Kalem

Son üç satır dersin çıkış noktasıdır. Üç çıktı da okunamaz görünür ve üçü de yaklaşık aynı uzunluktadır. Görünüş hiçbir şey söylemez; tablolar söyler.

Uzunluk sütunları ilk ayrımı verir. Girdi uzadığında kodlamanın çıktısı 44’ten 92’ye, şifrelemenin çıktısı 64’ten 112’ye çıkar — ikisi de girdiyle birlikte büyür, çünkü ikisi de girdinin tamamını taşır. Karmanın çıktısı iki girdide de 44 karakterdir. Sabit uzunluk, karmanın girdiyi taşımadığının doğrudan kanıtıdır: 64 karakterlik bir girdi de 6 kilobaytlık bir dosya da aynı 32 bayta iner. İçine sığmayan bilgi geri çıkarılamaz.

Belirlenimcilik sütununda üçü de evet verir; aynı girdi her zaman aynı çıktıyı üretir. Bu özellik doğrulamayı mümkün kılan şeydir ve aynı zamanda ikinci derste ölçülecek bir kısıtın kaynağıdır: iki kayıt eşitse çıktıları da eşittir.

Geri dönüş tablosu asıl ölçümdür ve dördü de gerçekten denenmiştir. Kodlanmış değer elde hiçbir kalem yokken açıldı — geri dönüş, çıktıyı gören herkesin yapabileceği bir işlemdir. Şifrelenmiş değer doğru anahtarla açıldı, yanlış anahtarla açılmadı. Üçüncü satır ikinci gizli kalemi gösterir: şifreli metnin tek bir baytı değiştiğinde çözme başarısız oldu, çünkü kullanılan çalışma kipi çıktıya bir doğrulama etiketi ekler ve çözmeden önce onu sınar. Şifrelemenin geri dönüşü bu yüzden bir değil iki kaleme bağlıdır: anahtar ve bozulmamış şifreli metin. Karma satırında denenecek bir şey bile yoktur; ters işlev diye bir şey tanımlı değildir.

Kodlamanın Yeri ve Çıktıdan Ayırt Etme

Kodlamanın bir güvenlik işlevi olmaması, gereksiz olduğu anlamına gelmez. Kurgu ölçüm ağında şubeler arasında aktarılan paket, metin taşıyan bir kanaldan geçer ve ham baytların bir bölümü o kanalda ayraç ya da denetim karakteri olarak yorumlanır. Kodlama tam olarak bunu çözer: baytları kanalın güvenle taşıyabileceği bir alfabeye yazar. Tablodaki aktarim paketi satırında kodlamanın uygun çıkmasının nedeni budur — o alanda istenen şey gizlilik değil, bozulmadan varmaktır.

Karışıklık, kodlanmış bir değerin okunamaz görünmesinden doğar. Çıktıya bakarak üçünü ayırmak yine de mümkündür ve ayırt edici işaretler yukarıdaki çıktıda hazır durur. Kodlanmış değerin uzunluğu girdinin uzunluğuyla orantılıdır ve çözüldüğünde anlamlı metin verir; sondaki = dolgusu da kullanılan alfabenin işaretidir. Karmanın çıktısı girdiden bağımsız olarak hep aynı uzunluktadır — 32 bayt, bu alfabede 44 karakter. Şifrelenmiş değer girdiyle birlikte büyür ama çözüldüğünde anlamsız bayt verir ve genellikle sabit bir fazlalık taşır: buradaki 16 baytlık doğrulama etiketi bu fazlalıktır.

Bir kayıt görüntüsünde sabit uzunlukta 44 karakterlik alanlar görülüyorsa bu bir karma sütunudur; uzunluğu satırdan satıra değişen alanlar kodlama ya da şifrelemedir. Ayrım bir tahmin değil, ölçülebilir bir özelliktir ve denetim sırasında ilk bakılacak sütundur.

Karıştırmanın Sayılabilir Sonucu

Üç işlemin ayrımı bir terim tartışması değildir. Kurgu ölçüm ağında dört alan vardır ve her alanın iki özelliği bellidir: değerin sonradan geri istenip istenmediği, değerin gizli kalması gerekip gerekmediği. Bu iki özellik doğru işlemi belirler; yanlış seçim ise iki ayrı sayıya mal olur.

// kripto/karisim.mjs — kurgu olcum agindaki dort alanin amaci ile uc islemin
// eslestirilmesi (model): her yanlis eslesmenin kac kalemde sonuc verdigi.
// KT4: bir islemi amacinin disinda kullanmanin bedeli goruste degil kalem sayisinda
//      olculur: acilma icin gereken kalem ve geri donusu kaybedilen kayit.
const ALAN = [                       // kayit sayilari kurgudur
  { ad: "sayac okuma degeri",  kayit: 12400, geri: true,  gizli: true,  dogru: "sifreleme" },
  { ad: "saha ekibi parolasi", kayit:   340, geri: false, gizli: true,  dogru: "karma" },
  { ad: "aygit seri ozeti",    kayit: 12400, geri: false, gizli: false, dogru: "karma" },
  { ad: "aktarim paketi",      kayit: 12400, geri: true,  gizli: false, dogru: "kodlama" },
];
const ACILMA = { kodlama: 0, sifreleme: 1, karma: null };   // geri donus icin gereken kalem

function karar(a, islem) {
  if (islem === a.dogru)                 return ["uygun", ACILMA[islem], 0];
  if (islem === "karma")                 return ["geri donus yok", null, a.kayit];
  if (islem === "kodlama" && a.gizli)    return ["0 kalemle okunur", 0, 0];
  if (islem === "kodlama")               return ["ham deger kalir", 0, 0];
  if (!a.geri)                           return ["tek kok tumunu acar", 1, 0];
  return ["gereksiz kok", 1, 0];
}
const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const G = [-20, -11, 6, 7, 8, 8, -22];
yaz(G, "alan", "islem", "geri", "gizli", "acilma", "kayip", "  karar");
let uygun = 0, sifir = 0, kayip = 0;
for (const a of ALAN) for (const islem of ["kodlama", "sifreleme", "karma"]) {
  const [k, ac, ky] = karar(a, islem);
  if (k === "uygun") uygun++; else if (ac === 0) sifir++;
  kayip += ky;
  yaz(G, a.ad, islem, a.geri ? "evet" : "hayir", a.gizli ? "evet" : "hayir",
      ac === null ? "-" : ac, ky || "-", "  " + k);
}
console.log(`\n${ALAN.length * 3} eslesmeden ${uygun} uygun; ${sifir} eslesmede ham deger ` +
  `0 kalemle geri gelir, yanlis karma ${kayip.toLocaleString("tr-TR")} kaydin geri donusunu yok eder`);
alan                islem        geri  gizli  acilma   kayip  karar
sayac okuma degeri  kodlama      evet   evet       0       -  0 kalemle okunur
sayac okuma degeri  sifreleme    evet   evet       1       -  uygun
sayac okuma degeri  karma        evet   evet       -   12400  geri donus yok
saha ekibi parolasi kodlama     hayir   evet       0       -  0 kalemle okunur
saha ekibi parolasi sifreleme   hayir   evet       1       -  tek kok tumunu acar
saha ekibi parolasi karma       hayir   evet       -       -  uygun
aygit seri ozeti    kodlama     hayir  hayir       0       -  ham deger kalir
aygit seri ozeti    sifreleme   hayir  hayir       1       -  tek kok tumunu acar
aygit seri ozeti    karma       hayir  hayir       -       -  uygun
aktarim paketi      kodlama      evet  hayir       0       -  uygun
aktarim paketi      sifreleme    evet  hayir       1       -  gereksiz kok
aktarim paketi      karma        evet  hayir       -   12400  geri donus yok

12 eslesmeden 4 uygun; 3 eslesmede ham deger 0 kalemle geri gelir, yanlis karma 24.800 kaydin geri donusunu yok eder

On iki eşleşmenin dördü uygundur; sekizi bir bedel taşır ve bedellerin türü aynı değildir.

En sessiz kusur ilk satırdadır. Sayaç okuması kodlanmışsa kayıt okunamaz görünür ve bakan kişi korunmuş sanır; oysa açılma kalemi sıfırdır. Kodlamanın hiçbir gizli kalemi olmadığı için, kodlanmış bir değeri korunmuş saymak, korumasız bir değeri korunmuş yazmakla aynı şeydir. Aynı kusur parola satırında yinelenir ve orada kayıt sayısı 340’tır.

İkinci kusur ters yöndedir. Saha ekibi parolası şifrelenirse geri dönüş mümkündür — ve bu tam olarak istenmeyen şeydir. Şifreleme, 340 kaydın tamamını tek bir kaleme, anahtara bağlar. O kalem kırıldığında düşen kayıt sayısı 340’tır; karmada ise kırılacak ortak bir kalem yoktur. Bu satır, kursun ölçü ekseninin ilk somut örneğidir: yanlış işlem seçimi bir kök yaratır ve kök yaratmanın bedeli, kökün kırılması hâlinde düşen kalem sayısıdır.

Üçüncü kusur geri döndürülemez olandır. Sayaç okuması ya da aktarım paketi karmalanırsa değer korunmuş olmaz, kaybolur; iki alanda toplam 24.800 kayıt bir daha okunamaz. Bu kusur diğer ikisinin tersine sızıntı anında değil, ilk yazma anında ortaya çıkar ve geri alınamaz.

Kursun Üç Sütunu

Bu ders, kurs boyunca her mekanizmaya sorulacak üç soruyu kurar ve ilkini yanıtlar.

Güven kökü. Mekanizma neyi baştan doğru varsayıyor? Kodlamanın kökü yoktur — hiçbir şey varsaymaz, hiçbir şey de vaat etmez. Şifrelemenin kökü anahtarın gizli kalmasıdır. Karmanın kökü, iki farklı girdinin aynı çıktıyı vermemesidir ve bu kök sonraki dersin konusudur.

Kaç kalem aynı anda doğru olmalı. Kökten kullanıma kadar kaç bileşenin birlikte tutması gerekiyor? Şifrelemede ölçülen sayı ikidir: anahtar gizli kalmalı ve şifreli metin bozulmamış olmalı. Kodlamada sıfırdır. Karmada bir tanedir: fonksiyonun çakışma direnci.

Kök kırılırsa kaç kalem düşer. Anahtar sızarsa o anahtarla şifrelenmiş bütün kayıtlar düşer; tablodaki parola satırında bu 340’tır. Kodlamada kırılacak bir kök yoktur, çünkü hiçbir şey kapalı değildir. Karmada kök kırılırsa düşen şey kayıtların gizliliği değil, karşılaştırmanın anlamıdır.

Kurs boyunca her ders bu üç sütunu doldurur. “Şu algoritma güçlüdür” bir karar taşımaz; kökün adı, zincirin uzunluğu ve kırılma anında düşen kalem sayısı taşır. Üçüncü sütuna her zaman bir dördüncü soru eşlik eder: kök kırıldığında yenilemek ne tutuyor? Anahtar sızdığında yeni anahtar üretmek tek bir işlemdir, ama o anahtarla korunan 12.400 kaydın yeniden şifrelenmesi ve anahtarın ulaşması gereken her uca ulaştırılması ayrı ayrı sayılan kalemlerdir. Bu kursta ölçülen bedel, kırılmanın kendisi değil, kırılmadan sonra elle dokunulan kalem sayısıdır.

Özet

  • Üç işlem geri dönüş için gereken gizli kalem sayısıyla ayrılır: kodlama 0, şifreleme 2 (anahtar ve bozulmamış şifreli metin), karma için ise hiçbir kalem yetmez.
  • Kodlama ve şifrelemenin çıktısı girdiyle birlikte büyür (44→92 ve 64→112 karakter); karmanın çıktısı her girdide 44 karakterdir ve bu sabitlik girdinin taşınmadığının kanıtıdır.
  • Üç işlem de belirlenimcidir: aynı girdi her zaman aynı çıktıyı verir.
  • Dört alan ile üç işlemin on iki eşleşmesinden yalnız dördü uygundur; üç eşleşmede ham değer 0 kalemle geri gelir, iki eşleşmede 24.800 kaydın geri dönüşü yok olur.
  • Her mekanizma üç sütunla ölçülür: güven kökünün adı, kökten kullanıma kadar aynı anda doğru olması gereken kalem sayısı ve kök kırıldığında düşen kalem sayısı.

Sonraki Adım

Bu derste karmanın kökü bir cümleyle geçildi: iki farklı girdi aynı çıktıyı vermez. Oysa bu cümle olduğu gibi doğru olamaz. Karmanın çıktısı sabit uzunluktadır ve olası girdi sayısı sınırsızdır; dolayısıyla aynı çıktıyı veren farklı girdiler kesinlikle vardır. Kök, çakışmanın var olmaması değil, bulunamaması varsayımıdır. Sonraki ders bu varsayımı sayıya çevirir: çıktı kaç bit olduğunda ilk çakışma kaç denemede bulunur, ölçülen sayı kuramsal sınırla ne kadar uyuşur ve çıktı uzunluğu iki katına çıktığında aranan deneme sayısı ne olur. Aynı ölçü, kullanımdan kaldırılmış karma algoritmalarının neden adım adım terk edildiğini de açıklar.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat