Nigdy nie przechowuj haseł
Część sekcji Uwierzytelnianie i bezpieczeństwo ścieżki Node.js w Coddy. Lekcja 4 z 24.
Ludzie używają tych samych haseł w różnych miejscach, więc ujawnienie hasła w postaci jawnego tekstu może narazić na niebezpieczeństwo konta w innych serwisach. Zapisuj skrót hasła z solą: wartość pochodną, którą weryfikujesz przez ponowne jej obliczenie, zamiast ją dekodować.
const salt = randomBytes(16).toString('hex');
const key = await scryptAsync(inviteCode, salt, 32);
const saved = salt + '.' + key.toString('hex');Ten przykład łączy sól i klucz pochodny dla kodu zaproszenia. Separator pozwala podczas weryfikacji odzyskać sól i wyprowadzić kolejny klucz przy użyciu tych samych parametrów. W zadaniu dotyczącym haseł używasz własnego separatora i długości klucza. Generuj sól dla każdego nowego hasła, wyprowadzaj klucz, a następnie zapisuj oba. Skróty z solą nadal wymagają silnych haseł, ponieważ osoba atakująca może próbować odgadnąć hasło.
Wyzwanie
ŁatwyObecnie rejestracja zapisuje każde hasło dokładnie w takiej postaci, w jakiej zostało wpisane. Zmień to tak, aby zamiast niego zapisywała skrót z solą, dzięki czemu wyciek bazy danych nie ujawni haseł.
- W pliku
passwords.jszmieńhashPassword(password)tak, aby zwracała tekst zapisywany przez rejestrację w postaci: sól, dwukropek, skrót:- Sól to 16 losowych bajtów, generowanych od nowa przy każdym wywołaniu i zapisanych w systemie szesnastkowym: 32 znaki od 0 do 9 oraz od a do f.
- Skrót to klucz o długości 64 bajtów, który
scrypttworzy na podstawie hasła i soli; również jest zapisany w systemie szesnastkowym: 128 znaków. Trzeci argument funkcjiscryptAsyncokreśla długość klucza w bajtach. - Połącz je dwukropkiem. Zapisana wartość wygląda tak:
f2bba0669d9fa2d203afc7e61bf8f065:c3f7cae352e023a8d4766da9a316b5a2c844100efff22c4079f89a8ab8512ac91c33227481c3afa88c3ba0e88347f9e3e0c22dad9d55f19688a350f71be8dbd2
- Nie musisz zmieniać pliku
server.js. TrasaPOST /signupjuż wywołujehashPasswordi zapisuje zwróconą przez nią wartość. Dostępna jest też trasaGET /debug/users/:username, która pokazuje, co zapisano dla jednego użytkownika. Ta trasa istnieje tylko po to, żeby można było to sprawdzić; prawdziwa aplikacja nigdy jej nie ma.
Wypróbuj: Naciśnij „Uruchom”. Wyślij żądanie POST /signup z treścią {"username": "ada", "password": "correct horse"}. Otrzymasz status 201 i {"username": "ada"}. Wyślij tę samą treść, zmieniając nazwę użytkownika na "username": "bob". Następnie wyślij żądanie GET /debug/users/ada, a potem GET /debug/users/bob. Każda wartość passwordHash składa się z 32 znaków, dwukropka i kolejnych 128 znaków. Obie wartości są różne, mimo że ada i bob wybrali to samo hasło.
Spróbuj swoich sił
import { randomBytes, scrypt } from 'node:crypto';
import { promisify } from 'node:util';
const scryptAsync = promisify(scrypt);
// Przekształca hasło w tekst przechowywany przez signup.
// Na razie zachowuje hasło w postaci wpisanej przez użytkownika.
export async function hashPassword(password) {
return password;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Uwierzytelnianie i bezpieczeństwo
1Hasła
Bajty i zapis szesnastkowyWyprowadzanie klucza z hasłaNowa sólNigdy nie przechowuj hasełPorównywanie bajtów kluczaSprawdzanie hasłaZasady rejestracjiPoćwicz samodzielnie: Edytor online Express