SIKS / Predavanja / Vježbe
Zadatak: Izrada programa za provjeru autentikacije korisnika
Cilj Zadatka:
Autentikacija korisnika je važan aspekt sigurnosti u računalnim sustavima. Ovaj zadatak će demonstrirati kako implementirati program za provjeru autentikacije korisnika u Pythonu, uz primjenu različitih sigurnosnih mjera poput hashiranja lozinki, dodavanja soli i ograničavanja broja neuspjelih pokušaja prijave.
Teorijska podloga:
Hashiranje je proces transformacije lozinke u fiksnu duljinu niza znakova pomoću hash funkcije. Hashiranje je jednosmjerna operacija, što znači da se iz hasha ne može rekonstruirati izvorna lozinka. Hashiranje lozinki je sigurnija praksa od pohrane lozinki u izvornom obliku jer, čak I ako napadač dobije pristup bazi podataka, neće moći saznati izvorne lozinke.
Sol (engl. Salt) je nasumična vrijednost koja se dodaje lozinki prije hashiranja. Dodavanje soli otežava napade pomoću rainbow tablica I brute-force napade. Sol treba biti jedinstvena za svakog korisnika I pohranjena zajedno s hashom lozinke.
Ograničavanje broja neuspjelih pokušaja prijave je mjera zaštite od brute-force napada. Nakon određenog broja neuspjelih pokušaja, korisnički račun se privremeno blokira na neko vrijeme kako bi se spriječilo prekomjerno opterećenje sustava I otežali napadi.
Implementacija jednostavne autentikacije
Upute:
- Definiranje Korisničkih Podataka:
- Na početku programa definirajte rječnik
korisnici
koji će sadržavati korisnička imena kao ključeve i pripadajuće lozinke kao vrijednosti. Na primjer:korisnici = {'korisnik1': 'lozinka1', 'korisnik2': 'lozinka2'}
- Na početku programa definirajte rječnik
- Zahtjev za Unosom:
- Zatražite od korisnika da unese svoje korisničko ime i lozinku koristeći funkcije
input()
.
- Zatražite od korisnika da unese svoje korisničko ime i lozinku koristeći funkcije
- Provjera Autentikacije:
- Provjerite postoji li uneseno korisničko ime u rječniku
korisnici
. Ako postoji, provjerite odgovara li unesena lozinka pripadajućoj lozinki u rječniku. - Ako su i korisničko ime i lozinka točni, ispišite poruku “Uspješna autentikacija!”.
- Ako korisničko ime ne postoji ili lozinka nije točna, ispišite poruku “Pogrešno korisničko ime ili lozinka!”.
- Provjerite postoji li uneseno korisničko ime u rječniku
Napomena: Ovaj zadatak služi kao osnova za razumijevanje kako funkcionira autentikacija u programiranju. U stvarnim aplikacijama autentikacija zahtijeva mnogo složenije mehanizme sigurnosti, uključujući korištenje vanjskih biblioteka za upravljanje lozinkama i korisničkim sesijama.
Autentikacija korisnika kriptiranom lozinkom – simetrična kriptografija
Ako već imate kriptiranu lozinku generiranu korištenjem OpenSSL naredbe openssl enc -aes-256-cbc -in plaintext.txt -out encrypted_text.txt -pass file:symmetric_key.txt
, možemo jednostavno pročitati kriptiranu lozinku iz datoteke i koristiti je za dekripciju prilikom autentikacije korisnika.
import subprocess
# Unaprijed definirani kredencijali
korisnicko_ime = "korisnik123"
simetricni_kljuc_datoteka = "symmetric_key.txt"
kriptirana_lozinka_datoteka = "encrypted_text.txt"
# Funkcija za dekripciju lozinke
def dekriptiraj_lozinku():
output = subprocess.check_output(["openssl", "enc", "-d", "-aes-256-cbc", "-in", kriptirana_lozinka_datoteka, "-pass", "file:" + simetricni_kljuc_datoteka]).decode().strip()
return output
# Funkcija za autentikaciju korisnika
def autenticiraj_korisnika():
uneseno_korisnicko_ime = input("Unesite korisničko ime: ")
# Provjera postojanja simetričnog ključa
try:
# Pokušaj dekriptiranja lozinke
dekriptirana_lozinka = dekriptiraj_lozinku()
except subprocess.CalledProcessError:
print("Greška prilikom dekriptiranja lozinke.")
return
if uneseno_korisnicko_ime == korisnicko_ime:
unesena_lozinka = input("Unesite lozinku: ")
# Provjera ispravnosti lozinke
if unesena_lozinka == dekriptirana_lozinka:
print("Uspješno ste autenticirani.")
else:
print("Pogrešna lozinka. Pokušajte ponovno.")
else:
print("Pogrešno korisničko ime. Pokušajte ponovno.")
# Pozivanje funkcije za autentikaciju korisnika
autenticiraj_korisnika()
Ovaj kod čita kriptiranu lozinku iz datoteke encrypted_text.txt i dekriptira je koristeći simetrični ključ pohranjen u datoteci symmetric_key.txt. Nakon toga, provjerava se ispravnost unesene lozinke s dekriptiranom lozinkom. Ako su lozinke jednake, korisnik je uspješno autenticiran.
Umjesto korištenja simetrične kriptografije za enkripciju i dekripciju lozinki, razmotrite korištenje jednosmjernih hash funkcija, poput SHA-256, uz dodatak soli (salt). Hashiranje lozinke sa solju znatno otežava napade na lozinke koristeći metode kao što su “rainbow tables”.
Implementacija hashiranja:
1. Definiranje korisničkih podataka
Definirajte rječnik korisnici koji sadrži korisnička imena kao ključeve i pripadajuće hashirane lozinke kao vrijednosti.
import hashlib
korisnici = {
"korisnik1": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8", # SHA-256 hash od "lozinka1"
"korisnik2": "5c29a959abce4eda5f0e7a4e7ea53dce7280a8be29d7e15a3f556dcd6e3b6e7e" # SHA-256 hash od "lozinka2"
}
2. Provjera autentikacije
Implementirajte funkciju provjeri_autentikaciju koja prima korisničko ime i lozinku, te provjerava njihovu ispravnost.
def provjeri_autentikaciju(korisnicko_ime, lozinka):
if korisnicko_ime in korisnici:
lozinka_hash = hashlib.sha256(lozinka.encode()).hexdigest()
if lozinka_hash == korisnici[korisnicko_ime]:
return True
return False
3. Dodavanje soli prilikom hashiranja lozinke
Generirajte nasumičnu vrijednost soli i dodajte je lozinki prije hashiranja.
import os
sol = os.urandom(16) # Generiranje nasumične vrijednosti soli
lozinka_hash = hashlib.sha256((lozinka + sol).encode()).hexdigest()
4. Ograničavanje broja neuspjelih pokušaja
Implementirajte logiku za ograničavanje broja neuspjelih pokušaja prijave i privremeno blokiranje korisničkog računa.
import time
broj_pokusaja = 0
max_pokusaja = 3
vrijeme_blokade = 30 # sekundi
while broj_pokusaja < max_pokusaja:
korisnicko_ime = input("Unesite korisničko ime: ")
lozinka = input("Unesite lozinku: ")
if provjeri_autentikaciju(korisnicko_ime, lozinka):
print("Uspješna autentikacija!")
break
else:
broj_pokusaja += 1
print(f"Pogrešno korisničko ime ili lozinka. Pokušaj {broj_pokusaja}/{max_pokusaja}")
if broj_pokusaja == max_pokusaja:
print(f"Prekoračen broj pokušaja. Pokušajte ponovno za {vrijeme_blokade} sekundi.")
time.sleep(vrijeme_blokade)
broj_pokusaja = 0
import hashlib
import os
import time
# Definiranje korisničkih podataka s hashiranim lozinkama i solju
korisnici = {
"korisnik1": {
"salt": os.urandom(16),
"hash": ""
},
"korisnik2": {
"salt": os.urandom(16),
"hash": ""
}
}
# Inicijalno hashiranje lozinki
for korisnik, podaci in korisnici.items():
lozinka = "lozinka" + korisnik[-1] # Pretpostavka za primjer
salt = podaci["salt"]
podaci["hash"] = hashlib.sha256(lozinka.encode() + salt).hexdigest()
# Funkcija za provjeru autentikacije
def provjeri_autentikaciju(korisnicko_ime, lozinka):
if korisnicko_ime in korisnici:
korisnik = korisnici[korisnicko_ime]
salt = korisnik["salt"]
lozinka_hash = hashlib.sha256(lozinka.encode() + salt).hexdigest()
if lozinka_hash == korisnik["hash"]:
return True
return False
# Logika za ograničavanje broja neuspjelih pokušaja
max_pokusaja = 3
vrijeme_blokade = 10 # sekundi
def autenticiraj_korisnika():
broj_pokusaja = 0
while broj_pokusaja < max_pokusaja:
korisnicko_ime = input("Unesite korisničko ime: ")
lozinka = input("Unesite lozinku: ")
if provjeri_autentikaciju(korisnicko_ime, lozinka):
print("Uspješna autentikacija!")
break
else:
broj_pokusaja += 1
print(f"Pogrešno korisničko ime ili lozinka. Pokušaj {broj_pokusaja}/{max_pokusaja}")
if broj_pokusaja == max_pokusaja:
print(f"Prekoračen broj pokušaja. Pokušajte ponovno za {vrijeme_blokade} sekundi.")
time.sleep(vrijeme_blokade)
broj_pokusaja = 0
autenticiraj_korisnika()
Zaključak:
Ovaj zadatak prikazuje različite aspekte autentikacije korisnika i sigurnosne mjere koje se mogu implementirati kako bi se povećala sigurnost sustava. Hashiranje lozinki, dodavanje soli i ograničavanje broja neuspjelih pokušaja su ključne tehnike za zaštitu od napada i neovlaštenog pristupa. Važno je napomenuti da su prikazani primjeri ilustrativni i da u stvarnim aplikacijama treba koristiti provjerene i sigurne biblioteke za upravljanje lozinkama i autentikacijom. Implementacijom ovih sigurnosnih mjera, program za provjeru autentikacije korisnika postaje otporniji na različite vrste napada i pruža veću sigurnost korisničkih podataka.