PHP Şifreleme ve Güvenlik: password_hash() ve password_verify() Kullanımı
Parola güvenliği modern web uygulamalarında temel bir gereksinimdir. PHP, doğru kullanıldığında güçlü ve güncel şifreleme araçları sunar. Bu makalede password_hash() ve password_verify() fonksiyonlarının nasıl çalıştığını, neden her çalıştırmada farklı hash üretildiğini, doğru saklama ve yeniden hash stratejilerini ve yaygın hataları ele alacağız.
Giriş — Neden password_hash ve password_verify?
Eskiden geliştiriciler MD5 veya SHA1 gibi tek dönüşümlü fonksiyonları doğrudan kullanıyordu; bu yöntemler artık yetersiz ve tehlikelidir. PHP'nin password_hash() fonksiyonu, otomatik salt üretimi ve adaptif (maliyet ayarlı) algoritmalar kullanarak güvenli, tek yönlü parola hash'leri üretir. Doğrulama için ise password_verify() fonksiyonu güvenli ve zamanlama saldırılarına karşı duyarlı olmayan bir karşılaştırma sağlar.
Nasıl çalışır? Teknik özet
password_hash()
password_hash() şu özelliklere sahiptir:
- Güçlü, tek yönlü bir hash üretir.
- Salt otomatik olarak üretilir ve hash içinde saklanır; geliştiricinin manuel salt yönetmesine gerek yoktur.
- PASSWORD_DEFAULT gibi sabitler kullanıldığında PHP, önerilen adaptif algoritmayı (ör. bcrypt) ve varsayılan maliyeti uygular.
- Çıktı her çalıştırmada farklı olabilir; bu, her hash için farklı salt kullanıldığından beklenen davranıştır.
password_verify()
password_verify(), kullanıcıdan gelen düz metin parolayı, veritabanında saklanan hash ile karşılaştırır. Fonksiyon hash içindeki salt ve algoritma bilgilerini kullanır ve güvenli, sabit zamanlı bir karşılaştırma uygular:
- Fonksiyonu kullanmak, manuel karşılaştırma ve zamanlama saldırılarına açık kod yazma riskini ortadan kaldırır.
- Doğrulama başarılıysa true, başarısızsa false döner.
Hızlı örnek
Aşağıdaki örnek temel kullanım örneğini gösterir:
<?php
// Kayıt sırasında
$plainPassword = 'S3cureP@ssw0rd';
$hash = password_hash($plainPassword, PASSWORD_DEFAULT);
// $hash veritabanına kaydedilir (ör: users.password)
// Giriş doğrulaması sırasında
$entered = 'S3cureP@ssw0rd';
if (password_verify($entered, $hash)) {
// Başarılı doğrulama
} else {
// Hatalı parola
}
?>
Not: Yukarıdaki örnekte tek yapmanız gereken password_hash ile hash üretip veritabanına kaydetmek, girişte ise password_verify ile kontrol etmektir.
Neden aynı parola için farklı hash'ler üretilir?
Her call'da yeni bir salt üretilir; salt hash içinde tutulur ve bu sayede aynı parolanın farklı hash'leri oluşur. Bu, sözlük/saldırı tablolarının etkisini azaltır ve güvenliği artırır. Bu davranış normal ve arzu edilen bir durumdur.
En iyi uygulamalar ve öneriler
- Her zaman password_hash ve password_verify kullanın: Salt yönetimi ve sabit zamanlı karşılaştırma gibi karmaşık ve hata-prone konuları PHP sizin için halleder.
- PASSWORD_DEFAULT kullanın: PHP'nin önerdiği varsayılan adaptif algoritmayı kullanmak, zamanla daha güçlü algoritmalara geçiş yapılmasını kolaylaştırır.
- Maliyet (cost) ayarını gerektiğinde özelleştirin: Yüksek maliyet daha güvenli fakat daha maliyetlidir; sunucunuzun performansını test edin ve uygun bir cost değeri belirleyin.
- Migrare ihtiyaçları için password_needs_rehash kullanın: Algoritma veya cost değiştiğinde kullanıcı oturum açtığında hash'i yeniden oluşturup güncelleyin.
- Parola uzunluğu ve gücü: Minimum uzunluk ve zayıf parola kontrolleri uygulayın; bununla birlikte hash fonksiyonu parola karmaşıklığını sağlamaz, yalnızca saklama güvenliğini sağlar.
- Veritabanı kolon tipi: Hash'leri saklamak için en azından VARCHAR(255) kullanın; bazı algoritmalar uzun hash'ler üretebilir.
- Ek güvenlik katmanları: HTTPS zorunlu kılma, rate limiting (brute-force koruması), 2FA ve account lockout politikaları uygulayın.
Yeniden hash (rehash) stratejisi
Algoritma veya cost arttığında mevcut kullanıcı hash'lerini toplu olarak değiştirmek zor olabilir. Bu yüzden yaygın bir strateji şudur:
- Kullanıcı başarılı giriş yaptığında password_needs_rehash() ile mevcut hash kontrol edilir.
- Eğer yeniden hash gerekliyse, kullanıcı parolası üzerinden yeni hash üretilip veritabanında güncellenir.
<?php
// Giriş sırasında
if (password_verify($entered, $hash)) {
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
$newHash = password_hash($entered, PASSWORD_DEFAULT);
// Veritabanında güncelle
}
}
?>
Yaygın hatalar ve kaçınılması gerekenler
- Parolayı düz metin olarak saklamak — kesinlikle yapılmamalıdır.
- Manuel salt üretme — password_hash otomatik salt üretir; manuel salt karıştırmak hata kaynaklı olabilir.
- Eski/zayıf hash fonksiyonları kullanma (md5/sha1) — bunlar günümüz saldırılarına dayanıklı değildir.
- Zamanlama saldırılarına açık manuel karşılaştırmalar — password_verify bunu önler.
Depolama ve operasyonel hususlar
- Hash'leri veritabanına kaydederken uygun alan uzunluğu ve indeksleme stratejisini düşünün (genelde hash üzerinde arama yapılmaz, kullanıcı adı/email üzerinden arama yapılır).
- Veritabanı sızıntılarına karşı ek önlemler: sunucu güvenliği, en az yetki prensibi, düzenli yedekleme ve erişim kontrolleri.
- Giriş denemelerini sınırlayın, IP veya hesap bazlı rate limiting uygulayın.
Sonuç — Özet ve uygulama rehberi
password_hash() ve password_verify() PHP'de parola saklama ve doğrulama için güncel, güvenli ve kolay uygulanabilir bir temel sağlar. Temel adımlar:
- Kayıt: password_hash ile hash üret, veritabanına kaydet.
- Giriş: password_verify ile doğrula.
- Algoritma veya cost değiştiğinde password_needs_rehash ile kullanıcı oturumu esnasında hash'i güncelle.
- Ek güvenlik: HTTPS, rate limiting, 2FA ve veritabanı güvenliğini unutma.
Bu adımları takip ederek uygulamanızın parola yönetimini modern güvenlik standartlarına yaklaştırabilirsiniz. Parola güvenliği tek başına tüm tehlikeleri ortadan kaldırmaz; katmanlı güvenlik yaklaşımı her zaman daha etkilidir.