---
title: 'API Anahtarları'
source: 'https://academia.sh/tr/kurslar/kimlik-ve-yetki/api-anahtarlari'
course: 'Kimlik Doğrulama ve Yetkilendirme'
language: tr
updated: '2026-08-17T18:06:48+00:00'
license: 'CC BY-SA 4.0'
---

# API Anahtarları

Makine çağıranlar için üretilen uzun ömürlü kimlik bilgisinin entropisi, önek ve son karakterlerin işletim değeri, karma olarak saklanması, geçiş penceresiyle döndürülmesi ve kapsamla sınırlanması.

Buraya kadarki bütün akışlarda karşıda bir insan vardı: parola giren, onay ekranını okuyan,
ikinci etmeni sağlayan biri. Kütüphane servisini çağıranların bir bölümü ise insan değildir.
Gece çalışan bir toplu iş, komşu kurumun katalog eşitleyicisi, bir gösterge panosu — bunların
ne parolası vardır ne de bir onay ekranını okuyabilirler.

Bu çağıranlar için kullanılan kimlik bilgisine **API anahtarı** denir. Yapısı yalındır:
uzun, rastgele bir dizgi. Yalınlığı hem gücü hem zayıflığıdır — taşınması kolaydır,
sızması da kolaydır.

## Anahtar Neyi Kanıtlar

API anahtarı **kim olduğunu** kanıtlar, ne yapabileceğini değil. Bu ayrım kursun ilk
dersindeki ayrımın makineler için geçerli biçimidir: anahtar doğrulanır, yetki ayrıca
sınırlanır.

Anahtarın belirteçten farkı ömrüdür. Belirteç kısa yaşar ve yenilenir; anahtar aylarca
aynı kalır ve yapılandırma dosyalarında, sürekli tümleştirme ortamlarında, kap
görüntülerinde durur. Bu yüzden anahtarın tasarımında iki soru öne çıkar: sızdığında ne
kadar zarar verir ve ne kadar hızlı değiştirilebilir?

Aşağıdaki hesap anahtarın üretiminden döndürülmesine kadar bütün yaşam döngüsünü
çalıştırır.

```bash
cat > anahtar.mjs <<'EOF'
// anahtar.mjs — API anahtarinin uretimi, saklanmasi, dogrulanmasi ve dondurulmesi
import { randomBytes, createHash, timingSafeEqual } from "node:crypto";
import { DatabaseSync } from "node:sqlite";

// 1. Uretim: onek + rastgele govde. Onek anahtarin nereye ait oldugunu okunur kilar.
const ONEK = "kutup_";
function anahtarUret(bayt) {
  const govde = randomBytes(bayt).toString("base64url");
  return ONEK + govde;
}
const entropi = (bayt) => bayt * 8;
console.log("govde bayt  entropi (bit)  ornek uzunluk  kaba kuvvet icin gereken deneme (2^n)");
for (const b of [8, 16, 24, 32]) {
  console.log(`${String(b).padStart(10)} ${String(entropi(b)).padStart(14)} ${String(anahtarUret(b).length).padStart(14)}  2^${entropi(b) - 1}`);
}

// 2. Saklama: anahtarin kendisi degil karmasi tutulur; onek ve son dort karakter aranabilir.
const db = new DatabaseSync(":memory:");
db.exec(`CREATE TABLE api_anahtari (
  kimlik TEXT PRIMARY KEY, sahip TEXT NOT NULL, karma TEXT NOT NULL,
  kuyruk TEXT NOT NULL, durum TEXT NOT NULL, gecerlilik_sonu INTEGER)`);
const karmala = (a) => createHash("sha256").update(a).digest("hex");
function kaydet(kimlik, sahip, anahtar, gecerlilikSonu = null) {
  db.prepare("INSERT INTO api_anahtari VALUES (?,?,?,?,?,?)")
    .run(kimlik, sahip, karmala(anahtar), anahtar.slice(-4), "etkin", gecerlilikSonu);
}
const eski = anahtarUret(24);
kaydet("AK-1", "katalog-esitleyici", eski);
// Karma ve kuyruk her uretimde farklidir; burada yalniz uzunluklari yazdirilir.
console.log("\nsaklanan kayit (anahtarin kendisi yok):");
for (const s of db.prepare("SELECT kimlik, sahip, length(karma) AS karma_uzunluk, length(kuyruk) AS kuyruk_uzunluk, durum FROM api_anahtari").all())
  console.log("  " + JSON.stringify(s));

// 3. Dogrulama: sabit sureli karsilastirma; eslesme yoksa neden acikca yazilmaz.
const SAAT = 1_770_000_000;
function dogrula(sunulan, saat) {
  const k = karmala(sunulan);
  const satir = db.prepare("SELECT * FROM api_anahtari WHERE kuyruk = ?").all(sunulan.slice(-4))
    .find((s) => {
      const a = Buffer.from(s.karma, "hex"), b = Buffer.from(k, "hex");
      return a.length === b.length && timingSafeEqual(a, b);
    });
  if (!satir) return "red: gecersiz anahtar";
  if (satir.durum !== "etkin") return `red: anahtar ${satir.durum}`;
  if (satir.gecerlilik_sonu !== null && saat >= satir.gecerlilik_sonu) return "red: suresi gecmis";
  return `kabul (${satir.sahip})`;
}
console.log("\ndogrulama denemeleri");
console.log("  gecerli anahtar          -> " + dogrula(eski, SAAT));
console.log("  rastgele baska anahtar   -> " + dogrula(anahtarUret(24), SAAT));

// 4. Dondurme: yeni anahtar uretilir, eski bir gecis penceresi boyunca gecerli kalir.
const yeni = anahtarUret(24);
kaydet("AK-2", "katalog-esitleyici", yeni);
db.prepare("UPDATE api_anahtari SET gecerlilik_sonu = ? WHERE kimlik = 'AK-1'").run(SAAT + 3600);
const asamalar = [
  ["dondurmeden once", SAAT - 10],
  ["gecis penceresinde", SAAT + 60],
  ["pencere kapandiktan sonra", SAAT + 7200],
];
console.log("\nasama                      eski anahtar            yeni anahtar");
for (const [ad, saat] of asamalar)
  console.log(`  ${ad.padEnd(26)} ${dogrula(eski, saat).padEnd(23)} ${dogrula(yeni, saat)}`);

// 5. Sizinti sonrasi: iptal aninda etkili olur, sureye bakilmaz.
db.prepare("UPDATE api_anahtari SET durum = 'iptal' WHERE kimlik = 'AK-2'").run();
console.log("\niptalden sonra yeni anahtar -> " + dogrula(yeni, SAAT + 60));

// 6. Kapsam ve kaynak sinirlamasi: anahtar tek basina yetki degildir.
const SINIR = { "AK-1": { kapsamlar: ["katalog:oku"], agBloklari: ["10.0.0.0/8"] } };
console.log("\nanahtar basina sinir: " + JSON.stringify(SINIR["AK-1"]));
console.log("  anahtar dogrulanir, yetki ayrica kapsamla ve kaynak agiyla sinirlanir.");
EOF
node anahtar.mjs
```

```text
govde bayt  entropi (bit)  ornek uzunluk  kaba kuvvet icin gereken deneme (2^n)
         8             64             17  2^63
        16            128             28  2^127
        24            192             38  2^191
        32            256             49  2^255

saklanan kayit (anahtarin kendisi yok):
  {"kimlik":"AK-1","sahip":"katalog-esitleyici","karma_uzunluk":64,"kuyruk_uzunluk":4,"durum":"etkin"}

dogrulama denemeleri
  gecerli anahtar          -> kabul (katalog-esitleyici)
  rastgele baska anahtar   -> red: gecersiz anahtar

asama                      eski anahtar            yeni anahtar
  dondurmeden once           kabul (katalog-esitleyici) kabul (katalog-esitleyici)
  gecis penceresinde         kabul (katalog-esitleyici) kabul (katalog-esitleyici)
  pencere kapandiktan sonra  red: suresi gecmis      kabul (katalog-esitleyici)

iptalden sonra yeni anahtar -> red: anahtar iptal

anahtar basina sinir: {"kapsamlar":["katalog:oku"],"agBloklari":["10.0.0.0/8"]}
  anahtar dogrulanir, yetki ayrica kapsamla ve kaynak agiyla sinirlanir.
```

## Üretim: Entropi ve Önek

Çıktının ilk tablosu gövde uzunluğunun entropiye çevrimini gösteriyor. On altı baytlık bir
gövde yüz yirmi sekiz bit entropi taşır; kaba kuvvetle bulunması pratikte olanaksızdır. Daha
uzun anahtarlar ek güvenlik getirmez, yalnız yapılandırma dosyalarını şişirir.

Önek ise güvenlik değil **işletim** içindir. Anahtar bir günlüğe ya da kaynak koduna
sızdığında, önek onun hangi servise ait olduğunu tek bakışta söyler; sızıntı taramaları da
bu önekle çalışır. Aynı nedenle anahtarın son birkaç karakteri kayıtta saklanır: kullanıcı
"hangi anahtarı iptal edeyim" sorusunu ancak böyle yanıtlayabilir.

## Saklama: Anahtarın Kendisi Tutulmaz

İkinci bölüm saklanan kaydı gösteriyor ve kayıtta anahtarın kendisi yok. Tutulan şey
karması, arama için son dört karakteri ve durum bilgisidir.

Bunun sonucu, anahtarın **yalnız bir kez** gösterilebilmesidir: üretildiği anda kullanıcıya
verilir, sonra bir daha okunamaz. Kaybedilen anahtar kurtarılmaz, yenisi üretilir. Bu
kısıt bir kolaylık kaybı gibi görünür ama veritabanı sızıntısında anahtarların doğrudan
kullanılabilir olmasını engeller.

Parola saklamadan bir fark vardır: API anahtarı yüksek entropili ve rastgeledir, sözlük
saldırısına açık değildir. Bu yüzden yavaş karma gerekmez; hızlı bir karma yeterlidir ve
her istekte doğrulanacağı için tercih edilir. Doğrulamanın **sabit süreli** karşılaştırmayla
yapılması ise yine gereklidir.

## Döndürme: Geçiş Penceresi

Dördüncü bölüm döndürmeyi aşama aşama gösteriyor. Yeni anahtar üretilir ve eski anahtara
bir son tarih verilir; geçiş penceresinde **ikisi de** geçerlidir. Bu, çağıran tarafın
yapılandırmasını güncellemesi için zaman tanır.

Pencere olmadan döndürme bir kesintidir: anahtar değiştiği anda eski yapılandırmayla çalışan
her iş düşer. Pencerenin uzunluğu, çağıran tarafın dağıtım sıklığına göre seçilir ve
pencerenin sonunda eski anahtarın gerçekten kullanılmadığı **ölçülerek** doğrulanır — son
kullanım zamanı kayıtta tutulur.

Beşinci bölüm istisnayı gösteriyor: sızıntı durumunda pencere yoktur. İptal anında etkili
olur ve süre denetiminden önce çalışır; kesinti, sızmış bir anahtarın açık kalmasına yeğdir.

## Anahtar Tek Başına Yetki Değildir

Son bölüm anahtar başına sınırları listeliyor. Doğrulanmış bir anahtar, çağıranın kim
olduğunu söyler; ne yapabileceği kapsamla, nereden çağırabileceği kaynak ağı kısıtıyla
sınırlanır. Salt okuma yapan bir eşitleyicinin anahtarı yazma uç noktalarına erişememelidir
— bu, Kapsamlar ve İzinler dersindeki kuralın makine çağıranlar için uygulanmasıdır.

Anahtarın nerede saklandığı da tasarımın parçasıdır. Kaynak koduna, kap görüntüsüne ya da
sürüm kontrolüne yazılan anahtar, o depoya erişebilen herkese açıktır. Doğru yer,
çalışma zamanında okunan bir sır deposudur; Gizli Değerlerin Ayrılması dersindeki sınır
burada da geçerlidir.

## Özet

- API anahtarı, onay ekranı olmayan makine çağıranlar için kullanılan uzun ömürlü bir
  kimlik bilgisidir; kim olduğunu kanıtlar, yetkiyi kapsam belirler.
- Önek ve son karakterler işletim içindir: sızıntı taraması ve "hangi anahtarı iptal
  edeyim" sorusu bunlarla çalışır.
- Kayıtta anahtarın kendisi değil karması tutulur; anahtar yalnız üretildiği anda
  gösterilir. Yüksek entropili olduğu için hızlı karma yeterlidir, karşılaştırma sabit
  sürelidir.
- Döndürmede eski ve yeni anahtar bir geçiş penceresinde birlikte geçerlidir; sızıntıda
  pencere yoktur, iptal anında etkilidir.
- Anahtar sır deposunda durur; kaynak koduna, kap görüntüsüne ya da sürüm kontrolüne
  yazılmaz.

## Sonraki Adım

Anahtar, makine çağıranın tek kanıtıdır: onu elinde tutan çağırandır. İnsan kullanıcılarda
ise tek kanıta dayanmak yetersizdir — parola ele geçtiğinde hesabın tamamı açılır. Kursun bu
konudaki son dersi ikinci bir kanıt katmanını ele alıyor: hangi etmen türleri vardır, zaman
tabanlı kodun doğrulaması nasıl yapılır, saat kayması nasıl karşılanır ve kurtarma kodları
neden tek kullanımlıktır?
