Parola Hash'leme
Kullanıcılarımızın güvenliğini sağlamak için parolalarını asla okunabilir biçimde saklamayız; yalnızca izlerini (hash denir) saklarız. Hash'ten geriye giderek özgün parola elde edilemez. Hash'i oluşturmak için güvenli bir algoritma kullanmak önemlidir. Bu konuda bize Nette\Security\Passwords sınıfı yardım eder.
Framework, DI container'a security.passwords adıyla otomatik olarak Nette\Security\Passwords tipinde
bir servis ekler. Ona bağımlılık
enjeksiyonuyla aktarılmasını sağlayarak erişebilirsiniz.
use Nette\Security\Passwords;
class Foo
{
public function __construct(
private Passwords $passwords,
) {
}
}
__construct (string $algo=PASSWORD_DEFAULT, array $options=[])
Hash'i üretmek için hangi güvenli algoritmanın kullanılacağını seçer ve parametrelerini yapılandırırız.
Varsayılan PASSWORD_DEFAULT değeridir; yani algoritma seçimi PHP'ye bırakılır. Daha yeni, daha güçlü hash
algoritmaları ortaya çıkarsa algoritma yeni PHP sürümlerinde değişebilir. Bu yüzden ortaya çıkan hash'in uzunluğunun
değişebileceğinin farkında olmalı ve onu yeterince karakter alabilecek biçimde saklamalısınız; önerilen genişlik
255'tir.
bcrypt algoritmasının hash hızını cost parametresini değiştirerek ayarlama örneği: (2020'de varsayılan 10'dur, bir parolayı hash'lemek yaklaşık 80 ms sürer; cost 11 için yaklaşık 160 ms; cost 12 için yaklaşık 320 ms; ne kadar yavaşsa koruma o kadar iyidir, 10–12 hızı zaten yeterli koruma sayılır)
// parolaları bcrypt algoritmasının 2^12 (2^cost) yinelemesiyle hash'leyeceğiz
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);
Bağımlılık enjeksiyonu kullanarak:
services:
security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])
static bcrypt (?int $cost=null): Passwords
bcrypt algoritması için yapılandırılmış bir örnek oluşturur. $cost parametresi yukarıda anlatılan hash
hızını belirler; onu atlarsanız PHP'nin varsayılanı kullanılır.
$passwords = Passwords::bcrypt(12);
static argon2id (?int $memoryCost=null, ?int $timeCost=null, ?int $threads=null): Passwords
Argon2id algoritması için yapılandırılmış bir örnek oluşturur. Atlanan parametreler PHP varsayılanlarına
bırakılır. PHP, Argon2 desteği olmadan derlenmişse metot Nette\NotSupportedException fırlatır.
$passwords = Passwords::argon2id(memoryCost: 1 << 17, timeCost: 4);
hash (string $password): string
Parolanın hash'ini üretir.
$res = $passwords->hash($password); // Parolayı hash'ler
Sonuç $res, hash'in kendisinin yanı sıra kullanılan algoritmanın tanımlayıcısını, ayarlarını ve
kriptografik bir tuzu (aynı parola için farklı bir hash üretilmesini sağlayan rastgele veri) içeren bir dizedir. Bu yüzden
geriye dönük uyumludur; örneğin parametreleri değiştirirseniz, önceki ayarlarla saklanmış hash'ler yine doğrulanabilir.
Bu sonucun tamamı veritabanında saklanır, dolayısıyla tuzu ya da ayarları ayrıca saklamaya gerek yoktur.
verify (string $password, string $hash): bool
Verilen parolanın verilen hash ile eşleşip eşleşmediğini saptar. $hash değerini, girilen kullanıcı adına
ya da e-posta adresine göre veritabanından alın.
if ($passwords->verify($password, $hash)) {
// doğru parola
}
needsRehash (string $hash): bool
Hash'in yapıcıda belirtilen seçeneklerle eşleşip eşleşmediğini saptar.
Örneğin hash cost değerini değiştirdiğinizde kullanmak yararlıdır. Doğrulama saklanan ayarlara göre yapılır ve
needsRehash() metodu true döndürürse, hash'i bu kez yeni parametrelerle yeniden oluşturup
veritabanına yeniden kaydetmek gerekir. Bu, kullanıcılar giriş yaptıkça saklanan hash'leri otomatik olarak
“yükseltir”.
if ($passwords->needsRehash($hash)) {
$hash = $passwords->hash($password);
// $hash değerini veritabanına kaydet
}