Κρυπτογράφηση κωδικού πρόσβασης

Για να διαχειριστούμε την ασφάλεια των χρηστών μας, δεν αποθηκεύουμε ποτέ τους κωδικούς τους σε μορφή απλού κειμένου, αλλά αποθηκεύουμε τον κατακερματισμό του κωδικού πρόσβασης. Ο κατακερματισμός δεν είναι αναστρέψιμη λειτουργία, ο κωδικός πρόσβασης δεν μπορεί να ανακτηθεί. Ο κωδικός πρόσβασης μπορεί όμως να σπάσει και για να κάνουμε τη διάσπαση όσο το δυνατόν πιο δύσκολη γίνεται, πρέπει να χρησιμοποιήσουμε έναν ασφαλή αλγόριθμο. Η τάξη Nette\Security\Passwords θα μας βοηθήσει σε αυτό.

Εγκατάσταση και απαιτήσεις

Το πλαίσιο προσθέτει αυτόματα μια υπηρεσία Nette\Security\Passwords στο DI container με το όνομα security.passwords, την οποία παίρνετε περνώντας την χρησιμοποιώντας dependency injection:

use Nette\Security\Passwords;

class Foo
{
	public function __construct(
		private Passwords $passwords,
	) {
	}
}

__construct($algo=PASSWORD_DEFAULT, array $options=[])string

Επιλέγει ποιος ασφαλής αλγόριθμος χρησιμοποιείται για κατακερματισμό και πώς να τον ρυθμίσετε.

Η προεπιλογή είναι PASSWORD_DEFAULT, οπότε η επιλογή του αλγορίθμου επαφίεται στην PHP. Ο αλγόριθμος μπορεί να αλλάξει σε νεότερες εκδόσεις της PHP όταν υποστηρίζονται νεότεροι, ισχυρότεροι αλγόριθμοι κατακερματισμού. Επομένως, θα πρέπει να γνωρίζετε ότι το μήκος του προκύπτοντος κατακερματισμού μπορεί να αλλάξει. Επομένως, θα πρέπει να αποθηκεύετε τον προκύπτοντα κατακερματισμό με τρόπο που να μπορεί να αποθηκεύσει αρκετούς χαρακτήρες, 255 είναι το συνιστώμενο πλάτος.

Έτσι θα χρησιμοποιήσετε τον αλγόριθμο bcrypt και θα αλλάξετε την ταχύτητα κατακερματισμού χρησιμοποιώντας την παράμετρο cost από την προεπιλεγμένη 10. Το έτος 2020, με κόστος 10, ο κατακερματισμός ενός κωδικού πρόσβασης διαρκεί περίπου 80ms, με κόστος 11 διαρκεί 160ms, με κόστος 12 τότε 320ms, η κλίμακα είναι λογαριθμική. Όσο πιο αργά τόσο το καλύτερο, το κόστος 10–12 θεωρείται αρκετά αργό για τις περισσότερες περιπτώσεις χρήσης:

// θα κατακερματιστούν οι κωδικοί πρόσβασης με 2^12 (2^cost) επαναλήψεις του αλγορίθμου bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

Με έγχυση εξάρτησης:

services:
	security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])

hash(string $passwords): string

Δημιουργεί hash κωδικού πρόσβασης.

$res = $passwords->hash($password); // Καταστρέφει τον κωδικό πρόσβασης

Το αποτέλεσμα $res είναι μια συμβολοσειρά που, εκτός από το ίδιο το hash, περιέχει το αναγνωριστικό του αλγορίθμου που χρησιμοποιήθηκε, τις ρυθμίσεις του και το κρυπτογραφικό salt (τυχαία δεδομένα που διασφαλίζουν ότι θα παραχθεί διαφορετικό hash για τον ίδιο κωδικό πρόσβασης). Επομένως, είναι συμβατό προς τα πίσω, για παράδειγμα, αν αλλάξετε τις παραμέτρους, μπορούν να επαληθευτούν οι κατακερματισμοί που έχουν αποθηκευτεί με τις προηγούμενες ρυθμίσεις. Όλο αυτό το αποτέλεσμα αποθηκεύεται στη βάση δεδομένων, οπότε δεν υπάρχει ανάγκη να αποθηκεύσετε ξεχωριστά το αλάτι ή τις ρυθμίσεις.

verify(string $password, string $hash)bool

Βρίσκει αν ο δεδομένος κωδικός πρόσβασης ταιριάζει με τον δεδομένο κατακερματισμό. Λαμβάνει το $hash από τη βάση δεδομένων με βάση το όνομα χρήστη ή τη διεύθυνση ηλεκτρονικού ταχυδρομείου.

if ($passwords->verify($password, $hash)) {
	// Σωστός κωδικός πρόσβασης
}

needsRehash(string $hash): bool

Βρίσκει αν ο κατακερματισμός ταιριάζει με τις επιλογές που δίνονται στον κατασκευαστή.

Χρησιμοποιήστε αυτή τη μέθοδο όταν για παράδειγμα αλλάζετε τις παραμέτρους κατακερματισμού. Η επαλήθευση του κωδικού πρόσβασης θα χρησιμοποιήσει τις παραμέτρους που είναι αποθηκευμένες με τον κατακερματισμό και αν το needsRehash() επιστρέψει true, θα πρέπει να υπολογίσετε ξανά τον κατακερματισμό, αυτή τη φορά με τις ενημερωμένες παραμέτρους, και να τον αποθηκεύσετε ξανά στη βάση δεδομένων. Αυτό διασφαλίζει ότι οι κατακερματισμοί των κωδικών πρόσβασης θα “αναβαθμίζονται” αυτόματα όταν οι χρήστες εγγράφονται.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// αποθήκευση του $hash στη βάση δεδομένων
}
έκδοση: 4.0