PHP

PHP’de password_hash ile Şifre Saklama

PHP'de password_hash ile Şifre Saklama

Web uygulamalarında kullanıcı hesaplarının güvenliği, veritabanında saklanan parolaların doğru şekilde korunmasıyla doğrudan ilişkilidir. Geçmişte sıkça tercih edilen zayıf algoritmalar veya düz metin (plain-text) saklama pratikleri, günümüz donanım gücü karşısında saniyeler içinde çözülebilmektedir. PHP, geliştiricilerin modern kriptografik standartlara uygun parola yönetimi yapabilmesi için yerleşik parola hashleme fonksiyonları sunar. Bu mimarinin temel taşı ise password_hash fonksiyonudur.

Geleneksel Hash Yöntemlerinin Riskleri

Uzun yıllar boyunca PHP projelerinde MD5 ve SHA1 gibi algoritmalar parola saklamak amacıyla kullanıldı. Ancak bu fonksiyonlar şifreleme veya güvenli parola saklama için değil, veri bütünlüğünü hızlıca doğrulamak (checksum) amacıyla tasarlanmıştır.

Hızlı çalışan algoritmalar, parola güvenliği açısından ciddi bir zafiyet doğurur. Güncel GPU (grafik işlemci) kümeleri, saniyede milyarlarca MD5 denemesi yapabilmektedir. Bu durum, sızdırılan veritabanlarındaki parolaların “rainbow table” (gökkuşağı tabloları) veya doğrudan kaba kuvvet (brute-force) saldırılarıyla kolayca açığa çıkmasına neden olur.

Güvenli bir parola saklama algoritmasının şu iki temel kritere sahip olması gerekir:

  • Yavaş ve hesaplama maliyeti yüksek olmalıdır.
  • Her parola için rastgele ve benzersiz bir tuz (salt) değeri otomatik üretilmelidir.

password_hash() Fonksiyonunun Temel Kullanımı

PHP 5.5 sürümüyle birlikte çekirdeğe dahil edilen password_hash(), geliştiriciyi tuz oluşturma ve algoritma karmaşasından kurtaran standart bir yapıdır. Bu fonksiyon, parolayı tek yönlü olarak hashler ve her seferinde kriptografik olarak güvenli rastgele bir salt değeri üretir.

Aşağıdaki örnekte en basit haliyle bir parolanın nasıl hash haline getirildiği gösterilmektedir:

<?php
$parola = "KullaniciGucluSifresi!123";

$hashlenmisParola = password_hash($parola, PASSWORD_DEFAULT);

echo $hashlenmisParola;
?>

Yukarıdaki kod çalıştırıldığında çıktı yaklaşık olarak şu biçimde görünür:

$2y$10$abcdefghijklmnopqrstuv...

Bu çıktı rastgele karakterlerden oluşmaz; belirli bir standardı temsil eder. Çıktının ilk bölümü kullanılan algoritmayı (örneğin Bcrypt için $2y$), sonraki iki basamak maliyet (cost) faktörünü, devamındaki kısım otomatik üretilen tuzu (salt) ve en son kısım ise asıl parola özetini içerir. Dolayısıyla tuz değerini ayrı bir veritabanı sütununda saklamanıza gerek kalmaz.

Algoritma ve Maliyet (Cost) Seçimi

password_hash fonksiyonunun ikinci parametresi algoritmayı, üçüncü parametresi ise yapılandırma seçeneklerini tanımlar.

Algoritma Türleri

  • PASSWORD_DEFAULT: PHP’nin en güncel ve güvenli kabul ettiği algoritmayı seçer. PHP güncellemeleriyle bu algoritma değişebilir; günümüzde genellikle Bcrypt veya Argon2id işaret edilir.
  • PASSWORD_BCRYPT: Standart Blowfish tabanlı Bcrypt algoritmasını zorunlu kılar.
  • PASSWORD_ARGON2I ve PASSWORD_ARGON2ID: Parola güvenliğinde modern bir standart olan, bellek tüketimi yüksek ve donanımsal saldırılara karşı dayanıklı Argon2 varyantlarıdır. (PHP’nin Argon2 desteğiyle derlenmiş olması gerekir).

Maliyet Değerini Ayarlama

Bcrypt algoritmasında maliyet faktörü, algoritmanın kaç tur çalışacağını belirler. Varsayılan değer 10‘dur. Bu değer 1 artırıldığında hesaplama süresi iki katına çıkar. Maliyeti artırmak sunucu güvenliğini güçlendirir ancak aşırı yüksek değerler CPU yükünü artırarak uygulamanın yanıt süresini uzatabilir.

<?php
$parola = "GizliKelimeler456";

$ayarlar = [
    'cost' => 12
];

$hash = password_hash($parola, PASSWORD_BCRYPT, $ayarlar);

echo $hash;
?>

Bu örnekte cost değeri 12 olarak atanmıştır. İdeal maliyet değeri, sunucunuzun tek bir hash işlemini yaklaşık 50 ile 100 milisaniye arasında tamamlayabileceği seviyede tutulmalıdır.

Parola Doğrulama: password_verify()

Hashlenmiş bir verinin geri çözülmesi matematiksel olarak mümkün değildir. Kullanıcının giriş yapabilmesi için, girdiği düz metin parolanın veritabanındaki hash ile eşleşip eşleşmediği kontrol edilmelidir. Bu işlem için password_verify() fonksiyonu kullanılır.

<?php
$girilenParola = "KullaniciGucluSifresi!123";
$veritabanindakiHash = '$2y$10$EIX5V6f.N0K.w7eA9g0j9eM6x6j8j6x6j8j6x6j8j6x6j8j6x6j8.';

if (password_verify($girilenParola, $veritabanindakiHash)) {
    echo "Parola dogrulandi, oturum aciliyor.";
} else {
    echo "Gecersiz parola veya kullanici adi.";
}
?>

password_verify(), veritabanındaki hash metnini inceler; algoritmayı, maliyeti ve kullanılan tuzu oradan okur. Ardından girilen parolayı aynı parametrelerle yeniden hashleyip zamanlama saldırılarına (timing attack) dayanıklı güvenli bir karşılaştırma yapar.

Hash Güncelleme: password_needs_rehash()

Zaman içinde sunucu donanımınız güçlenebilir veya PHP sürümünüz güncellendiğinde varsayılan algoritma değişebilir. Eski kullanıcıların veritabanındaki hashlerini yeni maliyet veya algoritma standardına yükseltmek için kullanıcıların oturum açtığı anı yakalamak gerekir. Bunun için password_needs_rehash() kullanılır.

<?php
$girilenParola = "KullaniciGucluSifresi!123";
$kullaniciHash = $veritabaniKaydi['parola_hash'];

$yeniAyarlar = ['cost' => 12];

if (password_verify($girilenParola, $kullaniciHash)) {
    if (password_needs_rehash($kullaniciHash, PASSWORD_DEFAULT, $yeniAyarlar)) {
        $yeniHash = password_hash($girilenParola, PASSWORD_DEFAULT, $yeniAyarlar);
        // $yeniHash degeri veritabaninda guncellenmelidir.
    }
    
    // Oturum islemlerine devam edilir.
}
?>

Bu yöntem sayesinde kullanıcıların şifre sıfırlamasına gerek kalmadan, veritabanı güvenliği kademeli olarak ve kesintisiz biçimde modern standartlara yükseltilir.

Veritabanı ve Uygulama Mimarisi İpuçları

  • Veritabanınızda parola alanını saklarken VARCHAR(255) uzunluğunda bir sütun kullanın. Bcrypt çıktıları 60 karakter sürse de Argon2 gibi yeni algoritmalar daha uzun dizeler üretebilir.
  • Asla kendi tuzunuzu (custom salt) elle üretip password_hash() fonksiyonuna harici vermeye çalışmayın. PHP’nin tuz parametresi PHP 7.0 ile birlikte kullanımdan kaldırılmış (deprecated) ve otomatik üretim zorunlu hale getirilmiştir.
  • Hashleme istemci tarafında değil, daima sunucu tarafında yapılmalıdır. İstemci ile sunucu arasındaki veri akışının güvenliği ise SSL/TLS sertifikası (HTTPS) ile sağlanmalıdır.

Özet ve Sonraki Adımlar

PHP’nin yerleşik password_hash ve password_verify fonksiyonları, modern web güvenliğinin vazgeçilmez bir parçasıdır. Geliştiricilerin ek kütüphanelere ihtiyaç duymadan, endüstri standardı olan Bcrypt ve Argon2 algoritmalarını kolayca projelerine entegre etmelerini sağlar.

Güvenlik altyapınızı bir adım öteye taşımak için giriş denemelerini kısıtlayan “rate limiting” mekanizmalarını inceleyebilir ve uygulamanıza iki faktörlü kimlik doğrulama (2FA) katmanı eklemeyi değerlendirebilirsiniz.

#backend geliştirme#password_hash#php#siber güvenlik#şifreleme

Комментарии

Комментариев пока нет. Будьте первым.

Оставить комментарий

Комментарии публикуются после одобрения администратором.