Het proces voor het verifiëren van het wachtwoord van een gebruiker omvat verschillende stappen, waarbij de nadruk ligt op best practices op het gebied van beveiliging in plaats van het wachtwoord in platte tekst op te slaan. Hier volgt een overzicht van hoe het doorgaans werkt:
1. Wachtwoordopslag (op de juiste manier):
* Hashing: In plaats van het wachtwoord van de gebruiker rechtstreeks op te slaan, slaat het systeem een cryptografische *hash* van het wachtwoord op. Een hash is een eenrichtingsfunctie; het is gemakkelijk om de hash uit het wachtwoord te berekenen, maar vrijwel onmogelijk om het originele wachtwoord uit de hash af te leiden.
* Zouten: Om de beveiliging nog verder te verbeteren, wordt vóór het hashen een willekeurig *salt* aan het wachtwoord toegevoegd. Het zout is een unieke, willekeurig gegenereerde reeks tekens. Dit maakt het voor aanvallers veel moeilijker om vooraf berekende hashtabellen (regenboogtabellen) te gebruiken om wachtwoorden te kraken, zelfs als ze toegang krijgen tot de database.
* De `salt` wordt doorgaans samen met het wachtwoord `hash` opgeslagen in het gebruikersrecord.
* Sterke hashing-algoritmen: Moderne systemen gebruiken robuuste hash-algoritmen zoals:
* bcrypt: Adaptief hash-algoritme dat langzaam en rekentechnisch duur is, waardoor het zeer resistent is tegen brute-force-aanvallen. Het omvat het genereren en opslaan van zout in de hasj zelf.
* Argon2: Een moderner en geheugenhard hash-algoritme, vaak beschouwd als de opvolger van bcrypt.
* cryptie: Een andere belangrijke afleidingsfunctie die is ontworpen om rekenintensief te zijn, waardoor het moeilijker wordt om wachtwoorden te kraken.
2. Inloggen/authenticatieproces:
1. Gebruikersinvoer: De gebruiker voert zijn gebruikersnaam en wachtwoord in het inlogformulier in.
2. Zout ophalen: Het systeem haalt de *salt* die bij de ingevoerde gebruikersnaam hoort, op uit de gebruikersdatabase.
3. Hasen met zout: Het systeem neemt het door de gebruiker ingevoerde wachtwoord en de opgehaalde *salt*, combineert deze en past vervolgens hetzelfde hash-algoritme toe dat werd gebruikt toen het wachtwoord oorspronkelijk werd opgeslagen.
4. Vergelijking: De resulterende hash uit stap 3 wordt vergeleken met de opgeslagen wachtwoordhash voor die gebruiker in de database.
5. Verificatie:
* Als de twee hashes overeenkomen: Het is zeer waarschijnlijk dat de gebruiker het juiste wachtwoord heeft ingevoerd. De gebruiker wordt geverifieerd en er wordt een sessie tot stand gebracht.
* Als de hashes niet overeenkomen: Het ingevoerde wachtwoord is onjuist. De gebruiker wordt de toegang geweigerd en ontvangt doorgaans een foutmelding.
Waarom dit veilig is:
* Geen wachtwoorden in platte tekst: Het systeem slaat het daadwerkelijke wachtwoord *nooit* op in leesbare tekst, dus zelfs als de database wordt gecompromitteerd, hebben de aanvallers geen directe toegang tot de wachtwoorden.
* Zout voorkomt aanvallen op regenboogtafels: Het unieke zout voor elke gebruiker maakt regenboogtabellen (vooraf berekende hashtabellen) ineffectief. Een aanvaller zou voor *elk* salt een regenboogtabel moeten genereren, wat rekenkundig onbetaalbaar is.
* Langzame hashing voorkomt brute-force-aanvallen: Moderne hash-algoritmen (zoals bcrypt, Argon2 en scrypt) zijn bewust ontworpen om langzaam te zijn. Dit betekent dat een aanvaller niet snel een groot aantal wachtwoordgissingen kan proberen.
Codevoorbeeld (conceptueel - Python met bcrypt):
```python
bcrypt importeren
def hash_password(wachtwoord):
"""Hashes een wachtwoord met behulp van bcrypt met een willekeurig gegenereerde salt."""
# Genereer een zout
zout =bcrypt.gensalt()
# Hash het wachtwoord met behulp van het zout
hashed_password =bcrypt.hashpw(wachtwoord.encode('utf-8'), salt)
return hashed_password, salt #Retourneer zowel de hash als de salt zodat de salt bij de hash kan worden opgeslagen
def verificatie_wachtwoord(ingevoerd_wachtwoord, opgeslagen_hash, opgeslagen_salt):
""Verifieert of het ingevoerde wachtwoord overeenkomt met de opgeslagen hash."""
# Hash het ingevoerde wachtwoord met het opgeslagen zout
hashed_entered_password =bcrypt.hashpw(entered_password.encode('utf-8'), opgeslagen_salt)
# Vergelijk de gegenereerde hash met de opgeslagen hash
return hash_entered_password ==opgeslagen_hash
Voorbeeldgebruik (bij het aanmaken van een nieuwe gebruiker):
wachtwoord ="mijnGeheimWachtwoord123"
gehasht_wachtwoord, salt =hash_wachtwoord(wachtwoord)
Sla het gehashte_wachtwoord en de salt op in de database (gekoppeld aan de gebruiker)
Voorbeeldgebruik (tijdens inloggen):
enter_password ="mySecretPassword123" #Gebruiker verstrekt tijdens inloggen
Haal de opgeslagen_hash en opgeslagen_salt op uit de database op basis van de gebruikersnaam
opgeslagen_hash =b'$2b$12$eK11wE0GqJ8dK9j7cQh9yOC9/s8/6rXlG13N/L604qG1V14k6yDna' # Voorbeeld - opgeslagen van bovenaf
opgeslagen_salt =b'$2b$12$eK11wE0GqJ8dK9j7cQh9yO' # Voorbeeld - opgeslagen van bovenaf
if verificatie_wachtwoord(ingevoerd_wachtwoord, opgeslagen_hash, opgeslagen_salt):
print("Wachtwoord geverifieerd! Inloggen gelukt.")
anders:
print("Onjuist wachtwoord. Inloggen mislukt.")
```
Belangrijke overwegingen:
* Wachtwoordcomplexiteit: Dwing wachtwoordcomplexiteitsregels af (minimale lengte, vereiste tekens) om wachtwoorden moeilijker te raden te maken.
* Snelheidslimiet: Implementeer snelheidsbeperkingen bij inlogpogingen om brute-force-aanvallen te voorkomen. Vergrendel accounts na een bepaald aantal mislukte pogingen.
* Tweefactorauthenticatie (2FA): Gebruik 2FA voor een extra beveiligingslaag. Zelfs als het wachtwoord in gevaar komt, heeft een aanvaller nog steeds een tweede factor nodig (bijvoorbeeld een code van een mobiele app).
* Regelmatige beveiligingsaudits: Voer regelmatig beveiligingsaudits uit om potentiële kwetsbaarheden te identificeren en aan te pakken.
* Bibliotheken up-to-date houden: Houd hashbibliotheken en afhankelijkheden bijgewerkt om te profiteren van de nieuwste beveiligingspatches.
* Mechanismen voor het opnieuw instellen van wachtwoorden: Implementeer veilige mechanismen voor het opnieuw instellen van wachtwoorden met behulp van e-mailverificatie of beveiligingsvragen.
Door deze principes te gebruiken, kunnen systemen wachtwoorden effectief verifiëren en tegelijkertijd gebruikersgegevens beschermen tegen compromissen. Het is een cruciaal aspect van de algehele veiligheid. |