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.

Kurulum ve gereksinimler

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
}
versiyon: 4.x