Ga naar hoofdinhoud

Wachtwoorden: een hash in je server

De sha256 uit les 3 gaat nu je server in: /registreer bewaart de hash, en /inloggen vergelijkt hash met hash.

Twee regels anders​

Zet import hashlib bovenaan main.py. In /registreer wordt de regel db[naam] = wachtwoord:

db[naam] = hashlib.sha256(wachtwoord.encode()).hexdigest()

In de database staat nu de hash. /inloggen moet daarom de hash van het ingetypte wachtwoord vergelijken, met dezelfde berekening. De regel met de if wordt:

if db.get(naam) == hashlib.sha256(wachtwoord.encode()).hexdigest():

Dat werkt omdat hetzelfde wachtwoord altijd dezelfde hash geeft.

Opnieuw registreren en inloggen​

In gebruikers.db staan nog de wachtwoorden als gewone tekst. Gooi het bestand weg en draai registreer.py en lees_database.py opnieuw. Maak daarna een scriptje inloggen.py dat drie pogingen doet: Sara met haar wachtwoord, Sara met een letter ernaast, en Bob, die geen account heeft:

import httpx

adres = "http://127.0.0.1:8000/inloggen"

pogingen = [("sara", "welkom123"), ("sara", "welkom124"), ("bob", "welkom123")]
for naam, wachtwoord in pogingen:
antwoord = httpx.post(adres, data={"naam": naam, "wachtwoord": wachtwoord})
print(f"{naam}, {wachtwoord}: {antwoord.json()['bericht']}")
Zo ziet je main.py er nu uit
import hashlib

from fastapi import FastAPI, Form, HTTPException
from sqlitedict import SqliteDict

app = FastAPI()

@app.post("/registreer")
async def registreer(naam: str = Form(...), wachtwoord: str = Form(...)):
with SqliteDict("gebruikers.db") as db:
if naam in db:
raise HTTPException(status_code=400, detail="Deze naam is al bezet")
db[naam] = hashlib.sha256(wachtwoord.encode()).hexdigest()
db.commit()
return {"bericht": f"Welkom, {naam}"}

@app.post("/inloggen")
async def inloggen(naam: str = Form(...), wachtwoord: str = Form(...)):
with SqliteDict("gebruikers.db") as db:
if db.get(naam) == hashlib.sha256(wachtwoord.encode()).hexdigest():
return {"bericht": "Ingelogd"}
return {"bericht": "Naam of wachtwoord klopt niet"}

Les 5 en 6 veranderen niets aan je server; in les 7 gaat /registreer weer om.

De wachtwoorden zijn niet meer te lezen. Maar kijk naar Sara en Noor: dezelfde code. Daar gaat les 5 over.

Controlevraag
Iemand heeft een kopie van jouw gebruikers.db. Hij logt in met de naam sara, en typt als wachtwoord de code die daar bij Sara staat: 2a5c5f26… Komt hij binnen?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

Er gaat iets mis​

Sara kan niet inloggen​

registreer.py geeft drie keer {'detail': 'Deze naam is al bezet'}, en inloggen.py geeft ook bij Sara met welkom123 Naam of wachtwoord klopt niet.

Oorzaak: de oude gebruikers.db staat er nog. Daarin staat welkom123 als gewone tekst, en /inloggen vergelijkt dat met de hash van welkom123. Die twee zijn nooit gelijk. Nieuwe accounts komen er niet bij, want de namen bestaan al.

Oplossing: gooi gebruikers.db weg en draai registreer.py opnieuw. lees_database.py laat daarna codes zien.

Opdrachten​

Opdracht 1: Predict - Eén hoofdletter​

Een vierde gebruiker, Tim, registreert met het wachtwoord Welkom123, met een hoofdletter.

Vraag: lijkt de code bij Tim in de database op die van Sara? En zie je aan de database dat Tim en Sara bijna hetzelfde kozen?

Tip

Kijk naar de derde eigenschap in les 3.

Antwoord

Nee. Bij Tim staat 7bca025eff4fb877bea86faac56c909b65c97adfba23b7c1fb6b9772d34b420e, een heel andere code dan de 2a5c5f26… van Sara. Eén letter anders is een compleet andere hash, dus aan de database zie je niet dat hun wachtwoorden op elkaar lijken.

Door naar les 5: zout.