Kryptograficzny strażniku! Architekt Vitruvius wprowadza cię w najgłębsze tajemnice ochrony kodów skarbca Imperium. Password hashing to sztuka tworzenia nieodwracalnych szyfrów, które chronią sekrety legionistów nawet przed najzacieklejszymi wrogami!
W obozie legionowym każdy zasób musi być chroniony. Podobnie w aplikacjach - hasła użytkowników to najcenniejsze zasoby, które wymagają najlepszych metod ochrony.
Password hashing to proces przekształcania hasła w nieodwracalny ciąg znaków (hash). To jak tworzenie unikalnego odcisku palca dla każdego hasła - można go sprawdzić, ale nie można z niego odtworzyć oryginalnego hasła.
1// ❌ ZŁE PODEJŚCIE - zwykłe szyfrowanie
2const encryptedPassword = encrypt('my-secret-password', 'encryption-key');
3// Można odszyfrować: decrypt(encryptedPassword, 'encryption-key')
4
5// ✅ DOBRE PODEJŚCIE - hashowanie
6const hashedPassword = await bcrypt.hash('my-secret-password', 12);
7// Nie można odwrócić procesu!1// npm install bcrypt
2// npm install -D @types/bcrypt
3
4import * as bcrypt from 'bcrypt';
5
6@Injectable()
7export class PasswordService {
8 private readonly saltRounds = 12; // Siła hashowania
9
10 async hashPassword(plainPassword: string): Promise<string> {
11 console.log('Tworzenie bezpiecznego szyfrowania hasła...');
12
13 // Generowanie salt i hashowanie
14 const hashedPassword = await bcrypt.hash(plainPassword, this.saltRounds);
15
16 console.log(`✅ Hasło zaszyfrowane: ${hashedPassword.substring(0, 20)}...`);
17
18 return hashedPassword;
19 }
20
21 async verifyPassword(
22 plainPassword: string,
23 hashedPassword: string
24 ): Promise<boolean> {
25 console.log(' Sprawdzanie hasła...');
26
27 const isValid = await bcrypt.compare(plainPassword, hashedPassword);
28
29 console.log(`${isValid ? '✅' : '❌'} Wynik weryfikacji: ${isValid}`);
30
31 return isValid;
32 }
33
34 // Sprawdzenie czy hasło wymaga re-hashowania (zmiana saltRounds)
35 async needsRehash(hashedPassword: string): Promise<boolean> {
36 try {
37 // bcrypt automatycznie wykrywa siłę hasła z hasha
38 const currentRounds = this.extractSaltRounds(hashedPassword);
39 return currentRounds < this.saltRounds;
40 } catch (error) {
41 return true; // Jeśli nie można określić, lepiej re-hashować
42 }
43 }
44
45 private extractSaltRounds(hash: string): number {
46 // Format bcrypt: $2b$12$...
47 const parts = hash.split('$');
48 return parseInt(parts[2], 10);
49 }
50}Pamiętaj: hasło to klucz do zasóbnicy legionariusza - musi być chroniony jak najcenniejszy zasób w aplikacji!
W następnym ćwiczeniu poznamy Refresh Tokens - system przedłużania przepustek do systemu fortu!