İçeriğe geç
academia.sh

Ders 04 / 12

Depo Geçmişinde Sır Tarama

940 dizi sabitinde dört desenin birlikte çalışması: entropi eşiği 0,60'tan kapalıya çekildiğinde eşleşme 855'ten 519'a inerken yanlış pozitif oranı 68,0'dan ancak 52,8'e düşer, çünkü gürültünün kaynağı entropi değil 442 eşleşmenin 270'ini yanlış çıkaran anahtar sözcük desenidir; 310 sırrın 50'si hiçbir desene takılmaz ve 26'sı tek bir sınıftadır. Üç yerleşim aynı desen kümesini taşır: her yapıda çalışma ağacı 1 057 dakika tarayıp 18 sırra hiç bakmaz, artımlı fark 9 dakikaya iner ama geriye kalan 164 sırrı hiç görmez, bir kerelik tam tarihçe 48 dakikada geçmişin tamamını okur ve 14 sırrın yalnız orada durduğunu gösterir.

İçindekiler

Bir erişim anahtarı bir yapılandırma satırına elle yazıldığında derleme geçer, sınamalar geçer ve önceki üç denetim de temiz döner: değer geçerli bir dizedir, çalışan uçta hata üretmez, bir bağımlılık kaydına karşılık gelmez. Onu görecek denetim dosyaların içindeki dizi sabitlerine bakar.

Sır tarama (secret scanning), depo içeriğindeki dizi sabitlerini bir desen kümesinden geçirip gizli olma ihtimali taşıyanları çıkaran denetimdir. Güvenli Kodlama kursunda aynı depo geçmişi bir kez ölçülmüştü, ama ölçülen şey sırrın maruziyetiydi: bir değerin kaç işlem boyunca açık kaldığı, silmenin neyi kapatmadığı. Burada ölçülen şey denetimin kendisidir — hangi desen kaç bulgu üretiyor, gürültü hangisinden geliyor, hangi sır sınıfı hiçbir desene takılmıyor ve bütün bunlar hattan kaç dakika alıyor.

  • OD19. Depo geçmişi üç deponun ortak 1 800 işlemesi ve 940 dizi sabitidir; kurgudur ve hiçbir gerçek sır biçimi yazılmaz. Bir dizi sabiti bir dosyaya yazılmış değişmez metin değeridir; gerçekten gizli olup olmadığı modelin doğrusudur, tarayıcı yalnız biçime bakar.
  • OD20. Desen kümesi dörttür. Önek biçimi ve blok başlığı yalnız biçimi belli sınıfları yakalar. Anahtar sözcük ataması değere değil, değerin atandığı ada bakar. Entropi eşiği eşiğin üstünde kalan her diziyi alır ve ayarlanabilen tek desendir.
  • OD21. Entropi, dizinin karakter dağılımının düzensizliğini 0 ile 1 arasında veren model ölçüsüdür; rastgele değerler yukarıda, sözcükler aşağıda durur.
  • OD22. Bir dizinin çalışma ağacından çıkarılması onu geçmişten çıkarmaz ve döndürme değildir; bu, Güvenli Kodlama kursunda ölçülmüştü, burada girdi olarak alınır.
  • OD23. Tarayıcı 900. işlemede kurulur, ondan önce hiç koşmamıştır; yapılar on işlemede bir alınır, toplam 90 yapı. Taranan kalem başına 0,02, incelenen yanlış pozitif başına 4 model dakikası harcanır. Süreler veridir, ölçüm değildir.

Gürültüyü Hangi Desen Üretiyor

// sir.mjs — depo gecmisindeki dizi sabitleri desen kumesinden geciriliyor; olculen sey
// eslesme, gercek sir, yanlis pozitif ve hicbir desenin gormedigi kalemdir. MODELDIR.
export const TOHUM = 20260329, ISLEME = 1800, DIZI = 940, KALEM_DK = 0.02;
const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };
const r = uretec(TOHUM);

// [ad, pay, sir olasiligi, entropi tabani, entropi tavani, ada atanma olasiligi, bicim]
// sir = o sinifin gercekten gizli olma olasiligi; bicim = onek/blok deseninin tanidigi kalip.
export const SINIF = [
  ["onekli erisim anahtari", 0.09, 0.93, 0.70, 0.96, 0.55, "onek"],
  ["rastgele oturum sirri", 0.11, 0.82, 0.66, 0.94, 0.72, ""],
  ["ozel anahtar blogu", 0.04, 0.96, 0.55, 0.80, 0.10, "blok"],
  ["baglanti dizesi", 0.10, 0.68, 0.34, 0.72, 0.86, ""],
  ["sozcuk parola", 0.08, 0.62, 0.16, 0.40, 0.34, ""],
  ["ozet degeri", 0.17, 0.00, 0.74, 0.95, 0.12, ""],
  ["sinama yer tutucusu", 0.23, 0.03, 0.28, 0.82, 0.78, ""],
  ["tekil kimlik", 0.18, 0.00, 0.58, 0.86, 0.18, ""],
].map(([ad, pay, sir, e0, e1, ata, bicim]) => ({ ad, pay, sir, e0, e1, ata, bicim }));
const sinifSec = (u) => { let t = 0;
  for (const s of SINIF) { t += s.pay; if (u < t) return s; } return SINIF.at(-1); };

// Her dizi bir islemede girer, bir bolumu sonraki bir islemede calisma agacindan
// cikarilir. Cikarilmak sirri gecersiz kilmaz; tarihcede oldugu yerde durur.
export const DIZILER = Array.from({ length: DIZI }, (_, i) => {
  const s = sinifSec(r());
  const giris = Math.floor(r() * ISLEME), ent = s.e0 + r() * (s.e1 - s.e0);
  const silindi = r() < 0.30 ? giris + 1 + Math.floor(r() * (ISLEME - giris)) : null;
  return { i, sinif: s, sir: r() < s.sir, ent, ata: r() < s.ata, giris, silindi,
    rev: 1 + Math.floor(r() * 9) };
});

export const desenler = (esik) => [
  { ad: "onek bicimi", tut: (d) => d.sinif.bicim === "onek" },
  { ad: "blok basligi", tut: (d) => d.sinif.bicim === "blok" },
  { ad: "anahtar sozcuk atamasi", tut: (d) => d.ata },
  { ad: "entropi esigi", tut: (d) => d.ent >= esik },
];
export const eslerMi = (d, esik) => desenler(esik).some((p) => p.tut(d));

const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const sirlar = DIZILER.filter((d) => d.sir);
  console.log(`model (tohum ${TOHUM}): ${ISLEME} isleme, ${DIZI} dizi sabiti, ` +
    `${sirlar.length} tanesi gercekten sir; ${DIZILER.filter((d) => d.silindi).length} dizi ` +
    `calisma agacindan cikarilmis`);
  const y1 = gen([16, 10, 9, 9, 12, 12]);
  console.log("\nentropi esigi degisiyor, oteki uc desen sabit");
  console.log(y1(["entropi esigi", "eslesme", "gercek", "yanlis+", "yanlis+ %", "gorulmeyen"]));
  for (const t of [0.60, 0.80, 1.01]) {
    const e = DIZILER.filter((d) => eslerMi(d, t)), g = e.filter((d) => d.sir).length;
    console.log(y1([t > 1 ? "kapali" : t.toFixed(2), e.length, g, e.length - g,
      (100 * (e.length - g) / e.length).toFixed(1), sirlar.length - g]));
  }

  const ESIK = 0.80, ds = desenler(ESIK);
  const y2 = gen([24, 10, 9, 9, 12]);
  console.log(`\nesik ${ESIK.toFixed(2)}'de desen basina katki`);
  console.log(y2(["desen", "eslesme", "gercek", "yanlis+", "tek kaynak"]));
  for (const p of ds) {
    const l = DIZILER.filter((d) => p.tut(d));
    const tek = l.filter((d) => ds.filter((q) => q.tut(d)).length === 1 && d.sir).length;
    console.log(y2([p.ad, l.length, l.filter((d) => d.sir).length,
      l.filter((d) => !d.sir).length, tek]));
  }

  const y3 = gen([24, 7, 12, 13, 13]);
  console.log(`\nesik ${ESIK.toFixed(2)}'de sinifa gore gorulmeyen sir`);
  console.log(y3(["dizi sinifi", "dizi", "gercek sir", "eslesen sir", "gorulmeyen"]));
  for (const s of SINIF) {
    const l = DIZILER.filter((d) => d.sinif === s), sl = l.filter((d) => d.sir);
    const e = sl.filter((d) => eslerMi(d, ESIK)).length;
    console.log(y3([s.ad, l.length, sl.length, e, sl.length - e]));
  }
}
model (tohum 20260329): 1800 isleme, 940 dizi sabiti, 310 tanesi gercekten sir; 269 dizi calisma agacindan cikarilmis

entropi esigi degisiyor, oteki uc desen sabit
entropi esigi      eslesme   gercek  yanlis+   yanlis+ %  gorulmeyen
0.60                   855      274      581        68.0          36
0.80                   677      260      417        61.6          50
kapali                 519      245      274        52.8          65

esik 0.80'de desen basina katki
desen                      eslesme   gercek  yanlis+  tek kaynak
onek bicimi                     93       89        4          12
blok basligi                    39       37        2          32
anahtar sozcuk atamasi         442      172      270          86
entropi esigi                  281      105      176          15

esik 0.80'de sinifa gore gorulmeyen sir
dizi sinifi                dizi  gercek sir  eslesen sir   gorulmeyen
onekli erisim anahtari       93          89           89            0
rastgele oturum sirri       102          83           71           12
ozel anahtar blogu           39          37           37            0
baglanti dizesi              89          56           44           12
sozcuk parola                66          39           13           26
ozet degeri                 179           0            0            0
sinama yer tutucusu         214           6            6            0
tekil kimlik                158           0            0            0

İlk tablo ayarlanabilir tek düğmeyi sonuna kadar çeviriyor. Entropi eşiği 0,60’ta eşleşme 855 ve yanlış pozitif oranı yüzde 68,0; desen tamamen kapatıldığında eşleşme 519’a iniyor ama oran ancak yüzde 52,8’e düşüyor. Gürültünün üçte ikisi eşiğin dokunmadığı yerdedir. Kapatmanın bedeli de aynı satırda: gerçek bulgu 274’ten 245’e iniyor, görülmeyen sır 36’dan 65’e çıkıyor.

İkinci tablo kaynağı adıyla yazıyor. Anahtar sözcük ataması deseni tek başına 442 eşleşme üretiyor ve 270’i yanlış pozitif — eşik 0,80’deki bütün gürültünün üçte ikisi. Nedeni desenin ne yaptığındadır: değere değil, değerin atandığı ada bakar; adı bir parola alanına benzeyen her satır eşleşir, içindeki değer bir sınama yer tutucusu olsa da. Önek biçimi deseni 93 eşleşmede 4, blok başlığı 39 eşleşmede 2 yanlış pozitif veriyor. Bir desen kümesinin yanlış pozitif oranı ortalama bir değer değildir; neredeyse tamamı tek bir desenden gelir ve o desen kaldırılmadan oran düşmez.

Son sütun kaldırma kararını zorlaştırıyor. Aynı desen 86 gerçek sırrın tek kaynağıdır; blok başlığı 32, entropi eşiği 15, önek biçimi 12 kalemde tek kaynaktır. En gürültülü desen en çok tekil katkıyı veren desendir, bu yüzden karar kaldırmak değil onun bulgularını ayrı bir kuyruğa almaktır: 270 yanlış pozitif aynı listeye girdiğinde 86 tekil gerçek bulgu arasında kaybolur.

Üçüncü tablo eşikten bağımsız kör noktayı veriyor. Sözcük parola sınıfının 39 gerçek sırrının 26’sı hiçbir desene takılmıyor: entropisi düşüktür, öneki yoktur ve üçte ikisi bir parola adına atanmamıştır. Bağlantı dizesi ve rastgele oturum sırrı sınıfları da on ikişer kalem kaçırıyor; toplam 50 sır taranmış olduğu hâlde görülmüyor. Karşıt uç da tabloda: özet değeri ve tekil kimlik sınıflarında 337 dizi var ve içlerinde tek bir sır yok — ikisi de entropi ölçüsünde yukarıda durduğu için eşik düşürüldükçe raporu bunlar doldurur.

Tarihçenin Bedeli ve Artımlının Kör Noktası

// tarihce.mjs — ayni desen kumesi uc yerlesimde kosuyor: her yapida calisma agaci,
// her yapida artimli fark ve bir kereye mahsus tam tarihce. Sureler MODEL dakikasidir.
import { DIZILER, ISLEME, KALEM_DK, eslerMi } from "./sir.mjs";

const ESIK = 0.80, YAPI = 90, BASLANGIC = 900, INCELEME_DK = 4;
const komut = (y) => BASLANGIC + Math.round((y + 1) * (ISLEME - BASLANGIC) / YAPI);
const canli = (d, c) => d.giris <= c && (d.silindi === null || d.silindi > c);
const SIR = DIZILER.filter((d) => d.sir);
const KOMUTLAR = Array.from({ length: YAPI }, (_, y) => komut(y));
// Yalniz tarihcede duran dizi: hicbir yapi aninda calisma agacinda degil.
const yalnizTarihce = (d) => !KOMUTLAR.some((c) => canli(d, c));

// Bir yerlesim, her yapida hangi kalem kumesinin tarandigini soyler. Calisma agaci
// yerlesimi o andaki dosyalari, artimli yerlesim yalniz onceki yapidan beri gireni
// gorur; tam tarihce kurulus aninda gecmisteki her revizyonu bir kez okur.
const GECMIS = DIZILER.filter((d) => d.giris <= BASLANGIC);
function olc(ad, kume, birKerelik = 0) {
  const gorulen = new Set(), blokeYapi = new Set(), bakilan = new Set();
  let taranan = birKerelik;
  if (birKerelik) for (const d of GECMIS) {
    bakilan.add(d); if (eslerMi(d, ESIK)) gorulen.add(d);
  }
  for (let y = 0; y < YAPI; y++) {
    const liste = kume(komut(y), y ? komut(y - 1) : BASLANGIC);
    taranan += liste.length;
    for (const d of liste) {
      bakilan.add(d);
      if (gorulen.has(d) || !eslerMi(d, ESIK)) continue;
      gorulen.add(d); blokeYapi.add(y);
    }
  }
  const gercek = [...gorulen].filter((d) => d.sir);
  const yanlis = gorulen.size - gercek.length;
  return { ad, taranan, eslesme: gorulen.size, gercek: gercek.length, yanlis,
    bakilmadi: SIR.filter((d) => !bakilan.has(d)).length,
    kacan: SIR.filter((d) => bakilan.has(d) && !gorulen.has(d)).length,
    bloke: blokeYapi.size, dk: Math.round(taranan * KALEM_DK),
    incDk: yanlis * INCELEME_DK,
    silinmis: gercek.filter(yalnizTarihce).length };
}

const REVIZYON = GECMIS.reduce((a, d) => a + d.rev, 0);
const YERLESIM = [
  olc("her yapida calisma agaci", (c) => DIZILER.filter((d) => canli(d, c))),
  olc("her yapida artimli fark",
    (c, o) => DIZILER.filter((d) => d.giris > o && d.giris <= c)),
  olc("tam tarihce + artimli",
    (c, o) => DIZILER.filter((d) => d.giris > o && d.giris <= c), REVIZYON),
];

const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");
const y = gen([26, 9, 8, 9, 11, 13, 8, 11, 9]);
console.log(`${YAPI} yapi, ${BASLANGIC}. islemede kurulan tarayici, ${SIR.length} gercek sir; ` +
  `tam tarihce ${REVIZYON} dizi revizyonu okur, kalem basina ${KALEM_DK} model dakikasi`);
console.log(y(["yerlesim", "eslesme", "gercek", "yanlis+", "bakilmadi", "desen kacan",
  "bloke", "tarama dk", "inc. dk"]));
for (const o of YERLESIM) {
  console.log(y([o.ad, o.eslesme, o.gercek, o.yanlis, o.bakilmadi, o.kacan, o.bloke,
    o.dk, o.incDk]));
}

const tam = YERLESIM.at(-1);
console.log(`\ntam tarihce bir kez ${Math.round(REVIZYON * KALEM_DK)} dakika alip ` +
  `${tam.gercek} sirri buluyor; ${tam.silinmis} tanesi hicbir yapi aninda calisma agacinda ` +
  `degil, silinmis ama dondurulmedigi surece gecerli`);
console.log(`desen korlugu yerlesimden bagimsizdir: tam tarihcede ${tam.kacan} sir okundugu ` +
  `halde hicbir desene takilmiyor. Pahali olan tarama da degil inceleme: ${tam.dk} dakika ` +
  `tarama karsiliginda ${tam.incDk} dakika, cunku ${tam.eslesme} eslesmenin ${tam.yanlis} ` +
  `tanesi yanlis pozitiftir`);
90 yapi, 900. islemede kurulan tarayici, 310 gercek sir; tam tarihce 2378 dizi revizyonu okur, kalem basina 0.02 model dakikasi
yerlesim                    eslesme  gercek  yanlis+  bakilmadi  desen kacan   bloke  tarama dk  inc. dk
her yapida calisma agaci        640     246      394         18           46      89       1057     1576
her yapida artimli fark         341     127      214        164           19      89          9      856
tam tarihce + artimli           677     260      417          0           50      89         57     1668

tam tarihce bir kez 48 dakika alip 260 sirri buluyor; 14 tanesi hicbir yapi aninda calisma agacinda degil, silinmis ama dondurulmedigi surece gecerli
desen korlugu yerlesimden bagimsizdir: tam tarihcede 50 sir okundugu halde hicbir desene takilmiyor. Pahali olan tarama da degil inceleme: 57 dakika tarama karsiliginda 1668 dakika, cunku 677 eslesmenin 417 tanesi yanlis pozitiftir

Üç satır aynı dört deseni taşıyor; ayrıldıkları yer neye baktıklarıdır. En yaygın kurulum ikinci satırdır: her yapıda yalnız o yapının getirdiği farkı taramak. 9 dakika harcıyor ve 127 sır buluyor. Aynı satırda 164 sırrın hiç bakılmadığı yazılı — tarayıcı kurulmadan önce depoya girmiş kalemler. Artımlı bir denetim onlara asla uğramaz ve her koşumda temiz rapor verir, çünkü baktığı küme her zaman yenidir. Bir artımlı taramanın kapsama listesi kurulduğu işlemedir; o tarih raporda yazılı değilse sıfır bulgu ile hiç bakılmamış olmak ayırt edilemez.

Birinci satır bu boşluğu pahalı kapatıyor. Her yapıda çalışma ağacının tamamını taramak 1 057 dakika harcıyor — artımlı yerleşimin yüz on yedi katı. Karşılığında kurulmadan önce girmiş ve hâlâ duran sırları görüyor: hiç bakılmayan sayısı 164’ten 18’e iniyor. Kalan 18 kalem hiçbir yapı anında çalışma ağacında değildir. Bloke sütunu üç yerleşimi ayırmıyor: üçü de 90 yapının 89’unu en az bir kez durduruyor, çünkü bloklayan şey gerçek sır değil, kuyruğa düşen her yeni eşleşmedir.

Üçüncü satır sıralamayı tersine çeviriyor. Kuruluş anında geçmişin tamamını taramak bir kerelik 2 378 dizi revizyonu okur ve 48 dakika sürer; çalışma ağacı yerleşiminin dört yapıda harcadığından azdır. Karşılığında hiç bakılmayan sır sıfıra iner, gerçek bulgu 260’a çıkar ve bunların 14’ü hiçbir yapı anında çalışma ağacında değildir — silinmiş, ama silme döndürme olmadığı için hâlâ geçerli. Bu 14 kalem yalnız bu yerleşimde görünür. Tarihçeyi taramak pahalı bir iş değildir; pahalı olan onu her yapıda yeniden taramaktır.

Son iki sütun bedelin yerini yazıyor. Tam tarihçe yerleşiminde 57 dakika tarama karşılığında 1 668 dakika inceleme çıkıyor: bedelin yüzde 97’si 417 yanlış pozitifin açılıp kapatılmasıdır. Bir sır taramasının hattan aldığı sürenin ölçüsü koşum süresi değil, yanlış pozitif oranıdır, ve o oranın nereden geldiği bir önceki bölümde yazılıydı.

Özet

  • Ayarlanabilir tek desen olan entropi eşiği yanlış pozitif oranını yüzde 68,0’dan ancak 52,8’e indirir ve bu sırada gerçek bulgu 274’ten 245’e düşer.
  • Gürültünün kaynağı tek bir desendir: anahtar sözcük ataması 442 eşleşmenin 270’ini yanlış çıkarır, çünkü değere değil değerin atandığı ada bakar. Aynı desen 86 gerçek sırrın tek kaynağıdır, bu yüzden karar kaldırmak değil ayrı bir kuyruğa almaktır.
  • 310 sırrın 50’si taranmış olduğu hâlde hiçbir desene takılmaz; 26’sı tek bir sınıftadır — düşük entropili, öneksiz ve bir parola adına atanmamış sözcük parolalar.
  • Üç yerleşim üç ayrı kör nokta taşır: artımlı fark 9 dakikada koşar ama kurulmadan önceki 164 sırrı hiç görmez, her yapıda çalışma ağacı 1 057 dakika harcar ve 18’ini görmez, bir kerelik tam tarihçe 48 dakikada geçmişin tamamını okur ve yalnız orada duran 14 sırrı ortaya çıkarır.
  • Bedelin yüzde 97’si tarama değil incelemedir: 57 dakika koşum karşılığında 417 yanlış pozitif için 1 668 dakika harcanır.

Sonraki Adım

Dört denetim de aynı yerde durdu: depodaki dosyalar. Oysa üretime giden şey dosya değil bir imajdır — derlenmiş çıktı, gereken kitaplıklar ve altlarındaki işletim katmanı tek bir yapıda birleşir. Bu yapının açıkları iki ayrı yerden gelir ve düzeltme yolları benzemez: bir bölümü ekibin eklediği katmanlardadır, bir bölümü hiç dokunulmamış temel katmandan miras alınır. İkincisi için yazılacak tek satır kod yoktur; kapatan şey bir yükseltmedir. Sonraki ders bir imaj katman listesinde bu iki kaynağı ayırır ve temel katmanı yükseltmenin açıkların kaçını kapattığını sayar.

İ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