---
title: 'Kodda Gömülü Sırlar'
source: 'https://academia.sh/tr/kurslar/guvenli-kodlama/kodda-gomulu-sirlar'
course: 'Güvenli Kodlama'
language: tr
updated: '2026-08-17T18:06:42+00:00'
license: 'CC BY-SA 4.0'
---

# Kodda Gömülü Sırlar

Kurgu bir depo geçmişinde sırrın açık kaldığı işlem sayısı ve desen taramasının kapsaması: beş sırrın çalışma ağacında 124, geçmişte 223 işlem görünmesi, tarihçe temizlemenin on dokuz kopyanın on sekizine erişememesi, anlık görüntü taramasının beş sırdan yalnız birini görmesi ve aynı kuralın geçmişte 76,8 kat bulgu ile 0,69 yanlış alarm oranı üretmesi.

Önceki iki ders anahtarın ve belirtecin nasıl üretildiğini ölçtü ve ikisi de aynı varsayıma
dayandı: üretilen değerin yalnız onu üreten süreçte kaldığına. Bu varsayım bir bölüm değer için
hiç doğru olmaz. O değerler üretilmemiştir; bir yapılandırma satırına elle yazılmış, oradan da
sürüm denetimine girmiştir. Girdikleri anda bir dosyada değil, bir **geçmişte** dururlar ve
geçmişin kendine özgü bir ölçüsü vardır.

Gizli Değer Yönetimi dersi üretimdeki değerin döndürme penceresini ve sızdığında ne kadar süre
geçerli kaldığını ölçmüştü. Burada ölçülen şey saklama pratiği değil, **kapsamadır**: kaç işlemde
sır kalmış, silmek kaç işlemi kapatıyor, bir tarama kuralı kaç noktayı görüyor ve görmek için kaç
yanlış alarm ödeniyor. Aşağıdaki depo geçmişi bir modeldir; işlem sayıları, dosya adları ve
değerler kurgudur ve hiçbiri gerçek bir sır biçimi taşımaz.

## Depo Geçmişinde Bir Sır

**KI7 — bir değer işlendiği anda depo geçmişine girer; çalışma ağacından silinmesi geçmişten
silinmesi değildir.** Silme yeni bir işlemdir ve eski işlemler yerinde durur. Bir sırrın gerçekten
kapandığı an, değerin geçersiz kılındığı — döndürüldüğü — andır.

```js
// depo/gecmis.mjs — kurgu bir depo gecmisi (model): 60 islem, bes kurgu sir. Sir degerleri
// asagida kendi uretecimizle uretilir; gercek bir sir bicimi, gercek anahtar deseni ve
// gercek servis adi kullanilmaz. giren: degerin islendigi islem; silinen: calisma agacindan
// cikarildigi islem; dondurulen: degerin gecersiz kilindigi islem (null = hic).
export const ISLEM = 60;
let durum = 4703;
export const rast = () => (durum = (durum * 1103515245 + 12345) % 2 ** 31) / 2 ** 31;
const ABC = 'abcdefghijkmnpqrstuvwxyzACDEFGHJKLMNPQRTUVWXYZ2346789';
export const uret = (n) => Array.from({ length: n }, () => ABC[Math.floor(rast() * ABC.length)]).join('');

export const sirlar = [
  { ad: 'saha imza anahtari', giren: 7, silinen: 19, dondurulen: null },
  { ad: 'rapor aktarim parolasi', giren: 12, silinen: null, dondurulen: null },
  { ad: 'portal oturum tuzu', giren: 3, silinen: 41, dondurulen: 44 },
  { ad: 'alim ust anahtari', giren: 22, silinen: 26, dondurulen: null },
  { ad: 'is emri geri cagirma anahtari', giren: 33, silinen: 55, dondurulen: 51 },
];

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 yok = (x) => (x === null ? '-' : x);

// KI7: bir sir islendigi anda gecmise girer; calisma agacindan silinmesi gecmisten
// silinmesi degildir. Kapanma yalnizca dondurme ile olur.
const D = [-30, 8, 9, 12, 9, 10, 8];
yaz(D, 'sir', 'giren', 'silinen', 'dondurulen', 'agacta', 'gecmiste', 'acik');
let agacta = 0, gecmiste = 0, acik = 0;
for (const s of sirlar) {
  const a = (s.silinen ?? ISLEM) - s.giren;
  const g = ISLEM - s.giren;
  const c = (s.dondurulen ?? ISLEM) - s.giren;
  agacta += a; gecmiste += g; acik += c;
  yaz(D, s.ad, s.giren, yok(s.silinen), yok(s.dondurulen), a, g, c);
}
yaz(D, 'toplam', '', '', '', agacta, gecmiste, acik);
console.log(`agactan silinmis ama dondurulmemis sir: `
  + `${sirlar.filter((s) => s.silinen !== null && s.dondurulen === null).length}/${sirlar.length}`);

// KI8: tarihce temizleme yalnizca erisilen kopyayi degistirir; dondurme her kopyayi
// degersiz kilar. Kopya sayilari kurgudur.
console.log('\ndeger islendikten sonra ulastigi kopyalar:');
const tutucular = [
  ['merkezi depo', 1, true],
  ['gelistirici klonu', 9, false],
  ['ayna ve yedek', 2, false],
  ['yapi calisma alani ve gunlugu', 4, false],
  ['paketlenmis yapi ciktisi', 3, false],
];
const E = [-32, 8, 18, 10];
yaz(E, 'tutucu', 'kopya', 'temizleme erisir', 'dondurme');
for (const [ad, n, erisir] of tutucular) yaz(E, ad, n, erisir ? 'evet' : 'hayir', 'evet');
const toplam = tutucular.reduce((a, [, n]) => a + n, 0);
const erisilen = tutucular.filter(([, , e]) => e).reduce((a, [, n]) => a + n, 0);
yaz(E, 'toplam', toplam, `${erisilen}`, `${toplam}`);
console.log(`tarihce temizlemenin disinda kalan kopya: ${toplam - erisilen}/${toplam}`);
```

```
sir                              giren  silinen  dondurulen   agacta  gecmiste    acik
saha imza anahtari                   7       19           -       12        53      53
rapor aktarim parolasi              12        -           -       48        48      48
portal oturum tuzu                   3       41          44       38        57      41
alim ust anahtari                   22       26           -        4        38      38
is emri geri cagirma anahtari       33       55          51       22        27      18
toplam                                                           124       223     198
agactan silinmis ama dondurulmemis sir: 2/5

deger islendikten sonra ulastigi kopyalar:
tutucu                             kopya  temizleme erisir  dondurme
merkezi depo                           1              evet      evet
gelistirici klonu                      9             hayir      evet
ayna ve yedek                          2             hayir      evet
yapi calisma alani ve gunlugu          4             hayir      evet
paketlenmis yapi ciktisi               3             hayir      evet
toplam                                19                 1        19
tarihce temizlemenin disinda kalan kopya: 18/19
```

## Silmenin Kapatmadığı Şey

Üç sayı sütunu üç ayrı soruya karşılık geliyor ve üçü de aynı beş sır için farklı çıkıyor. Beş sır
çalışma ağacında toplam **124 işlem** boyunca görünüyor; aynı beş sır depo geçmişinde **223 işlem**
boyunca erişilebilir durumda; gerçekten açık kaldıkları süre ise **198 işlem**. Ortadaki sütun ile
soldaki arasındaki fark, silme işleminin ürettiği yanılsamanın büyüklüğüdür: doksan dokuz işlemlik
bir aralık "temizlendi" diye kapatılmış görünüyor ama içerik geçmişte duruyor.

Satırlar tek tek okununca ölçü daha keskinleşiyor. Alım servisinin üst anahtarı çalışma ağacında
yalnızca **dört işlem** kalmış — girdiği işlemden dört işlem sonra fark edilip silinmiş. Bu, hızlı
bir düzeltme gibi görünür. Geçmiş sütunu aynı değer için **38** yazıyor ve açık sütunu da 38, çünkü
değer hiç döndürülmemiş. Dört işlemlik bir görünürlük, otuz sekiz işlemlik bir açıklığa karşılık
geliyor. Aynı kalıp saha imza anahtarında da var: on iki işlem ağaçta, elli üç işlem açık.

Son satır düzenin doğru sırasını gösteriyor. İş emri geri çağırma anahtarı 51'inci işlemde
döndürülmüş, 55'inci işlemde silinmiş; açık kaldığı süre **18 işlem** ve bu, beş sırrın en kısası.
Ağaçta kalma süresi (22 işlem) açık kalma süresinden **uzun** olan tek satır budur. Önce döndürüp
sonra temizlemek, ölçüyü tersine çeviren tek sıradır.

İkinci tablo bunun nedenini sayıyor. İşlenen bir değer yayımlandıktan sonra on dokuz kopyaya
ulaşıyor: merkezî depo, dokuz geliştirici klonu, iki ayna ve yedek, dört yapı çalışma alanı ile
günlüğü, üç paketlenmiş yapı çıktısı. Tarihçeyi yeniden yazmak bunlardan **birine** erişiyor;
kalan **on sekizi** dokunulmadan duruyor. Klonların her biri ayrı bir işlemle güncellenmek
zorundadır, yapı günlükleri çoğunlukla değiştirilemez, paketlenmiş çıktı zaten dağıtılmıştır.
Döndürme sütunu ise on dokuzun on dokuzunda `evet` yazıyor — çünkü döndürme kopyayı silmez,
kopyayı **değersiz** kılar. Değer dağıldıysa tek çıkar döndürmektir; tarihçe temizlemek onun yerini
almaz, olsa olsa yeni bir kopya üretmeyi durdurur.

## Aynı Kural, İki Ayrı Tarama

**KI9 — bir tarama kuralı yalnızca taradığı kümedeki noktaları kapsar; anlık görüntü ile geçmiş iki
ayrı kümedir.** Aşağıdaki kural verilmiştir ve tartışılmaz: yirmi karakterden uzun ve karakter
entropisi 3,6'nın üstünde olan değer işaretlenir. Ölçülen şey kuralın kalitesi değil, aynı kuralın
iki ayrı küme üzerinde ne kapsadığıdır.

```js
// depo/tarama.mjs — ayni kurgu depo gecmisinde desen taramasi (model, kendi basina kosar).
// Kural verilmistir: uzunluk >= 20 ve karakter entropisi >= 3.6 olan deger isaretlenir.
// Degerler kendi uretecimizle uretilir; hicbiri gercek bir sir bicimi tasimaz.
const ISLEM = 60;
let durum = 4703;
const rast = () => (durum = (durum * 1103515245 + 12345) % 2 ** 31) / 2 ** 31;
const ABC = 'abcdefghijkmnpqrstuvwxyzACDEFGHJKLMNPQRTUVWXYZ2346789';
const uret = (n) => Array.from({ length: n }, () => ABC[Math.floor(rast() * ABC.length)]).join('');

// [dosya, deger, gizli mi, giren islem, silinen islem]
const kalemler = [
  ['saha/ayar.mjs', uret(32), true, 7, 19],
  ['rapor/aktar.mjs', uret(28), true, 12, null],
  ['portal/oturum.mjs', uret(30), true, 3, 41],
  ['alim/kaynak.mjs', uret(14), true, 22, 26],
  ['is-emri/uc.mjs', uret(26), true, 33, 55],
  ['izleme/ornek.mjs', uret(28), false, 0, null],
  ['portal/simge.mjs', uret(40), false, 0, null],
  ['yapi/surum.mjs', uret(24), false, 5, null],
  ['katalog/kimlik.mjs', uret(22), false, 0, null],
  ['saha/sinama.mjs', uret(21), false, 9, 38],
  ['ceza/ayar.mjs', './veri/gecici/ceza', false, 0, null],
  ['bildirim/ornek.mjs', 'DEGISTIR-BENI', false, 0, null],
  ['uyelik/tur.mjs', 'abone-standart-tarife', false, 0, null],
];

const entropi = (d) => {
  const say = {};
  for (const c of d) say[c] = (say[c] ?? 0) + 1;
  return -Object.values(say).reduce((a, n) => a + (n / d.length) * Math.log2(n / d.length), 0);
};
const KURAL = (d) => d.length >= 20 && entropi(d) >= 3.6;
const varMi = (k, islem) => islem >= k[3] && (k[4] === null || islem < k[4]);

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 D = [-30, 10, 8, 11, 11, 13, 8];
yaz(D, 'tarama', 'taranan', 'bulgu', 'yakalanan', 'kacirilan', 'yanlis alarm', 'oran');

const olc = (ad, cift, tekil) => {
  const bulgu = tekil ? new Set(cift.filter(([k]) => KURAL(k[1])).map(([k]) => k[1])).size
    : cift.filter(([k]) => KURAL(k[1])).length;
  const dogru = tekil ? new Set(cift.filter(([k]) => KURAL(k[1]) && k[2]).map(([k]) => k[1])).size
    : cift.filter(([k]) => KURAL(k[1]) && k[2]).length;
  const gizliToplam = tekil ? new Set(cift.filter(([k]) => k[2]).map(([k]) => k[1])).size
    : cift.filter(([k]) => k[2]).length;
  yaz(D, ad, cift.length, bulgu, dogru, gizliToplam - dogru, bulgu - dogru,
    bulgu ? ((bulgu - dogru) / bulgu).toFixed(2) : '-');
};

const son = kalemler.filter((k) => varMi(k, ISLEM - 1)).map((k) => [k]);
const gecmis = [];
for (let i = 0; i < ISLEM; i++) for (const k of kalemler) if (varMi(k, i)) gecmis.push([k, i]);
olc('anlik goruntu (son islem)', son, false);
olc('tum gecmis', gecmis, false);
olc('tum gecmis + tekillestirme', gecmis, true);

const gizliGecmis = gecmis.filter(([k]) => k[2]).length;
console.log(`\nson islemde duran gizli kalem: ${son.filter(([k]) => k[2]).length}/5;`
  + ` gecmiste gorunen gizli kalem-islem cifti: ${gizliGecmis}`);
const kacan = kalemler.filter((k) => k[2] && !KURAL(k[1]));
console.log(`kuralin kacirdigi gizli kalem: ${kacan.map((k) => `${k[0]} (uzunluk ${k[1].length})`).join(', ')}`);
console.log(`gecmis taramasinin anlik goruntuye gore bulgu carpani: `
  + `${(gecmis.filter(([k]) => KURAL(k[1])).length / son.filter(([k]) => KURAL(k[1])).length).toFixed(1)}x`);
```

```
tarama                           taranan   bulgu  yakalanan  kacirilan yanlis alarm    oran
anlik goruntu (son islem)              8       5          1          0            4    0.80
tum gecmis                           568     384        120          4          264    0.69
tum gecmis + tekillestirme           568       9          4          1            5    0.56

son islemde duran gizli kalem: 1/5; gecmiste gorunen gizli kalem-islem cifti: 124
kuralin kacirdigi gizli kalem: alim/kaynak.mjs (uzunluk 14)
gecmis taramasinin anlik goruntuye gore bulgu carpani: 76.8x
```

## Yanlış Alarmın Bedeli

Birinci satır kapsamayı en açık biçimde veriyor. Son işlemin çalışma ağacında yalnızca sekiz kalem
var ve bunların **yalnız biri** gizli. Anlık görüntü taraması o biri buluyor, kaçırdığı yok ve
mükemmel görünüyor. Oysa beş sırrın dördü zaten silinmiştir ve tarama onları hiç görmez. Kapsama
oranı bu satırda 1/5'tir ve tarama bunu bildirmez; bildirdiği sayı yakaladığı bir bulgudur.

Tablonun altındaki satır bu 1/5'i başka bir açıdan yazıyor: geçmişte gizli bir kalemin göründüğü
işlem çifti sayısı **124**'tür. Aynı sayı birinci tablonun "ağaçta" sütununun toplamıdır ve iki
ölçümün aynı modeli okuduğunu gösterir. Anlık görüntü taraması bu 124 çiftin yalnızca son
işlemdekini görür.

İkinci satır aynı kuralı tüm geçmişe uyguluyor. Taranan kalem-işlem çifti 568'e, bulgu 384'e
çıkıyor ve beş sırrın beşi de görünür hâle geliyor. Bulgu sayısı anlık görüntüye göre **76,8 kat**
artmış durumda. Yanlış alarm sayısı 264'tür ve oranı 0,69 — yani her üç bulgudan ikisi gizli
olmayan bir değerdir. Bu oran kuralın kötülüğünden değil, aynı zararsız değerin altmış işlemde
altmış kez sayılmasından geliyor.

Üçüncü satır bu çarpanı kaldırıyor. Bulgular içeriğe göre tekilleştirildiğinde 384 bulgu **dokuza**
iniyor: dördü gizli, beşi yanlış alarm, oran 0,56. İncelenecek kalem sayısı iki büyüklük sırası
küçülüyor ve kapsama hiç değişmiyor. Geçmiş taramasında ölçülmesi gereken şey bulgu sayısı değil,
**ayrı değer** sayısıdır; aksi hâlde tarama kendi gürültüsünü ölçer.

Son satır kuralın sınırını yazıyor: alım servisinin üst anahtarı on dört karakter uzunluğunda ve
eşiğin altında kaldığı için hiçbir taramada görünmüyor. Beş sırdan dördü kapsanıyor, biri dışarıda
kalıyor. Bu, taramanın kendi ölçüsüyle gösterilemeyen bir eksiktir; kaçırdığını ancak başka bir
yerden bilen biri sayabilir.

## Yeni Sır Eklendiğinde

Üçüncü sütun bu dersin en keskin ayrımını taşıyor. Desen taraması bir **kalıp değil, bir süzgeçtir**:
yarın eklenecek bir sır ancak eşiği geçerse kapsanır. Beş sırrın biri bugün eşiğin altındadır,
dolayısıyla yeni bir değerin kapsanma olasılığı ölçülmüş değil, umulan bir şeydir. Eşiği düşürmek
kapsamayı artırır ve yanlış alarmı büyütür; yanlış alarm oranı zaten 0,56'dır ve her artış inceleme
işini çoğaltır.

Sırrın kaynak ağacına hiç girmediği kalıp bu sorunu farklı bir yerden çözüyor. Değer çalışma anında
bir sır deposundan okunuyorsa kaynakta hiçbir zaman bir değer bulunmaz; kapsama, taramanın
bulduğuna değil, kaynakta hiç değer olmamasına dayanır. Yeni bir sır eklendiğinde kapsama
kendiliğinden sürer, çünkü değeri koda yazacak bir yer yoktur. Bu düzende tarama ortadan kalkmaz —
kalıbın **dışına çıkan** noktayı bulmak için kalır — ama artık tek savunma değildir. İki savunmanın
kapsaması aynı beş sırda ölçüldüğünde biri 4/5, öteki 5/5 verir ve aradaki bir satırlık fark, altmış
işlemlik bir geçmişte 38 işlemlik bir açıklığa karşılık gelir.

## Özet

- Beş sır çalışma ağacında 124 işlem, depo geçmişinde 223 işlem görünüyor; gerçekten açık kaldıkları
  süre 198 işlem. Silme, doksan dokuz işlemlik bir aralığı kapatılmış gösteriyor.
- Alım servisinin anahtarı ağaçta dört işlem kalmış ama hiç döndürülmediği için 38 işlem açık;
  ağaçta kalma süresi açık kalma süresinden kısa olduğu sürece silme bir ölçü vermez.
- Önce döndürüp sonra temizleyen tek satır en kısa açıklığı üretti: 18 işlem.
- İşlenen değer on dokuz kopyaya ulaşıyor; tarihçe temizleme birine erişiyor, on sekizi dışarıda
  kalıyor. Döndürme on dokuzunu birden değersiz kılıyor.
- Anlık görüntü taraması beş sırdan yalnız birini görüyor; aynı kural tüm geçmişte beşini de
  buluyor ama bulgu 76,8 kat artıyor ve yanlış alarm oranı 0,69 oluyor. İçerik tekilleştirmesi
  bulguyu dokuza indiriyor, kapsamayı değiştirmiyor.
- Desen taraması yeni sırrı ancak eşiği geçerse kapsıyor (4/5); değeri kaynağa hiç yazmayan kalıp
  yeni noktayı kendiliğinden kapsıyor.

## Sonraki Adım

Bu ders sırrın kaynak ağacında ve depo geçmişinde bıraktığı izi saydı. Değer kaynaktan çıkarılıp
bir depoya taşındığında bu iz kapanır — ama değer çalışma anında hâlâ süreçte durur ve süreç
konuşur. Bir istek hata verdiğinde geriye dönen yanıt, bir işlem yapıldığında yazılan günlük satırı,
bir çökme sonrası dosyaya düşen yığıt izi: hepsi sürecin içindeki değerlerin dışarı çıktığı
noktalardır. Sonraki ders bu noktaları kalem olarak sayar — kaç yanıt yığıt izi taşıyor, kaç günlük
satırı kimlik bilgisi ya da kişisel veri taşıyor, merkezî bir maskeleme katmanı kaçını kapatıyor ve
kaç kalem dışarıda kalıyor.
