Hash bcrypt class encryption

Door Sander D, 15 jaar geleden, 17.312x bekeken

Hash bcrypt is een hash waarbij een salt wordt gebruikt. Dit is om bruteforce aanvallen (zoals het aflopen van een rainbow tabel) te voorkomen. Op dit moment is dit één van de veiligste methodes om wachtwoorden op te slaan.

Deze methode is éénrichtingsverkeer. Het is vrij onmogelijk om het daadwerkelijke wachtwoord te achterhalen. Je moet hiervoor zowel de salt (sleutel), rondes en wachtwoord weten; wat het dus eigenlijk gewoon onmogelijk maakt.

Je kunt he om de volgende manier gebruiken:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$password
= 'jewachtwoord';

$bcrypt = new Bcrypt(15); // rounds
$hash = $bcrypt->hash($password);
$verification = $bcrypt->verify($password, $hash);
?>

Gesponsorde koppelingen

PHP script bestanden

  1. bcrypt_class.inc.php

 

Er zijn 12 reacties op 'Hash bcrypt class encryption'

PHP hulp
PHP hulp
0 seconden vanaf nu
 

Gesponsorde koppelingen
Jonet L
Jonet L
15 jaar geleden
 
0 +1 -0 -1
hoe kan je deze nieuwe vormm van beveiligen het beste toepassen op bestaande ww die via md5 zijn gecrypt?
Dos Moonen
Dos Moonen
15 jaar geleden
 
0 +1 -0 -1
Jonet L:
Voeg wat code toe aan je inlog precedure zodat wanneer de gebruiker nog een md5 hash heeft je het dan upgrade naar een bcrypt hash. Op dat moment heb je namelijk toegang tot het wachtwoord in plaintext.

En het liefst plaats je dan nog een mededeling zodat de gebruikers weten dat de beveiliging van hun wachtwoord opgekrikt wordt als de uit- en dan weer inloggen.
De VeeWee
de VeeWee
15 jaar geleden
 
@Dos:
Het probleem met deze aanpak, is dat je niet weet wanneer alle wachtwoorden geconverteerd zijn. Er zijn misschien wel gebruikers die nooit meer terugkeren naar uw website. Deze wachtwoorden blijven dan voor eeuwig in md5?

Stel er is een beveiligingslek en de hacker is met uw database gaan lopen. In die database zitten 60% md5 wachtwoorden en 40% bcrypt wachtwoorden. Dan kan de hacker die 60% te weten komen door de wachtwoorden die beginnen met "$2a$" te verwijderen. Deze md5 wachtwoorden kan hij dus perfect achterhalen via rainbow tables.

Hoe ga je dan die 60% md5 wachtwoorden na die lek beveiligen? Of ga je dan zeggen tegen de gebruiker: je hebt een jaar geleden iets besteld op onze website en daarna ben je niet meer op de site geweest, dus dat is gewoon dikke pech? Terwijl het uw verantwoordelijkheid is om deze veilig te houden?

Misschien is het beter om een (minder propere) oplossing te gebruiken, die een bcrypt wachtwoord maakt van de opgeslagen md5 wachtwoorden:
$bcrypt->hash(md5('wachtwoord'))
Hierbij kan je eventueel iets minder rounds instellen in bcrypt, zodat de berekening niet te traag word. Maar wat is dan een goed aantal rounds...?

Dan zit je natuurlijk ook nog met het probleem dat je al je wachtwoorden opnieuw moet gaan berekenen. Dit gaat toch wel een hele tijd duren voor je al de wachtwoorden geëncrypteerd hebt met bcrypt. Je kan dus best een lokale database opbouwen met een tabel: md5, bcrypt die voor elke unieke md5 een bcrypt hash maakt. Ten slotte kan deze tabel dan via sql uw productie database laten aanpassen. Dit proces gaat toch wel een hele tijd innemen als je site vele logins heeft.

De vraag is dus: wat is de beste oplossing?
Beide situaties zijn, zoals je kan lezen, niet ideaal...

Ik heb deze vraag nog even verder bekeken en dit is wel een oplossing waar ik achter sta:
http://stackoverflow.com/questions/10771198/migrate-old-md5-passwords-to-bcrypt-passwords

- Stap 1: nieuwe berekenen tijdens inloggen
- Stap 2: bezoekers die niet ingelogd zijn informeren over de nieuwe beveiliging en aanzetten tot inloggen
- Stap 3: Een nieuw (random) wachtwoord aanmaken voor de gebruikers die nog niet ingelogd zijn en hen op de hoogte brengen via e-mail
Dos Moonen
Dos Moonen
15 jaar geleden
 
0 +1 -0 -1
Luuk de Bresser
Luuk de Bresser
15 jaar geleden
 
0 +1 -0 -1
IK heb een vraag?
Waarom krijg ik als ik dit script 2x uitvoer 2x een verschillende hash.
en de als ik dan de eerste hash met $verification laat controleren dan klopt deze.
is het dit niet heel onlogisch en fout gevoelig omdat er meerdere hashes bestaan per wachtwoord.
De VeeWee
de VeeWee
15 jaar geleden
 
0 +1 -0 -1
Je encrypteerd uw wachtwoord met een willekeurige salt. Dit geeft dus als resultaat een willekeurige hash. Hierdoor zijn juist die rainbow attacks onmogelijk: de hacker kan geen woordenboek over uw database laten lopen, omdat deze willekeurig zijn.

Bij het verifieren van het wachtwoord, gebruik je deze hash als salt. Je berekend dus een nieuwe hash op basis van het ingegeven wachtwoord en de opgeslagen hash als salt. Als je dan hetzelfde resultaat krijgt, dan klopt het wachtwoord.

Dit is dus zeker verilig!

Verder gebruik je die rounds om het script te vertragen / versnellen. Hoeveelste hoger het aantal rounds, hoe langer het zal duren voor een hash is gegenereerd. Hierdoor kan je dus het bruteforcen ook tegen gaan. Je moet maar eens kijken hoe lang het duurt voor een wachtwoord te encrypteren met 16 rounds. Dit is aanzienlijk langer dan md5 of sha1. Een echte hel voor de hacker om uw hele database te gaan bruteforcen dus!
Steven dirickx
steven dirickx
15 jaar geleden
 
1 +1 -0 -1
@Jonet L, DOS, VeeWee: Je kan ook gewoon iedereen een nieuw wachtwoord sturen via e-mail en vragen om daarmee in te loggen en hun wachtwoord aan te passen.
Eddy E
Eddy E
15 jaar geleden
 
@ De VeeWee.... dus ipv een simpele sleep(3); wat je server met rust laat laat je de server 3 seconden volledig werken om iets voor elkaar te krijgen wat niet nodig is?
2000x hashen levert niets meer op dan 20x hashen. Behalve dat je maar 1% van de benodigde CPU vraagt.
En brute-forcers vinden het niet erg om je server plat te gooien met een te hoge CPU-load.
Wat als ze 100 requests tegelijkertijd doen, om de seconde na elkaar? Dat is 1000 verzoeken in 10 seconden.
Per verzoek schiet je CPU naar (zeg...) 5% per request.
O... dat is slechts 5000% van wat je CPU aankan. Gevolg: server plat (net als DDOS-aanvallen).

Een sleep(4) is veel effectiever, en minde zwaar voor je server. Met hetzelfde resultaat.
Bij een eerste inlogpoging geef je een sleep(1) op, bij de tiende inlogpoging (als je hem dan niet al blokkeert...) een sleep(10).

Laat hem dan maar eens 1000 requests doen. Dat duurt te lang, maar je CPU heeft het veel minder zwaar.
No One
No One
15 jaar geleden
 
0 +1 -0 -1
@Eddy Erkelens: waarom zit de rounds functie er dan in? ga er maar van uit dat de ontwikkelaars daar een bewuste keuze gemaakt hebben na veel onderzoek. Persoonlijk heb ik liever een server die tijdelijk plat ligt dan dat er wachtwoorden gejat worden, omdat de wachtwoorden vaak wachtwoorden zijn die door gebruikers op meerdere sites gebruikt worden etc.

daarnaast is die sleep alleen effectief als je bijvoorbeeld session_start hebt gedaan (session_start() locked het bestandje met de sessie informatie op de server waardoor andere programmatuur die gebruik maakt van die zelfde sessiebestand niet geladen kan worden, voor dat de vorige request klaar is met uitvoeren). Als je dus geen sessie gebruikt voor je goed en wel bent ingelogt heb je dus niks aan sleep. daarnaast ziet de gebruiker die gewoon even zijn wachtwoord niet gemakkelijk herinnerd de pagina steeds trager worden wat gebruiksvriendelijkheid niet echt bevorderd.

Je kan beter om het platgaan van je server én bruteforce tegen te gaan in je inlogscript er voor zorgen dat je weet wanneer de laatste inlogpoging was van een bepaalde gebruikersaccount of ip adres en dan zodoende de tijd tussen de inlogpogingen ophoogt. wel natuurlijk pas beginnen na 3 of vier keer inloggen zodat je een normale gebruiker de kans geeft om normaal zijn wachtwoord goed te typen. en dan kan je bijvoorbeeld na 10 of 15 pogingen eisen dat de gebruiker via wachtwoord vergeten zijn wachtwoord reset. Voordeel is dat je dan gelijk een blokkade hebt voor dat IP-adres.
Donny Wie weet
Donny Wie weet
14 jaar geleden
 
0 +1 -0 -1
Is dit voor alle PHP versies? Of alleen de nieuwste? Ik weet van MD5 dat je dat in je INSERT string plaats ( '".mysql_real_escape_string(md5($wachtwoord))."') werkt dat met deze nieuwe crypt ook?
No One
No One
14 jaar geleden
 
0 +1 -0 -1
ja dat werkt met crypt ook ja
PHP hulp
PHP hulp
0 seconden vanaf nu
 

Gesponsorde koppelingen
Jonas K
Jonas K
13 jaar geleden
 
0 +1 -0 -1
Hoe moet je het ingevulde wachtwoord in een form controleren met hetgene dat in database staat? en welk moet juist in database worden opgeslagen?

Om te reageren heb je een account nodig en je moet ingelogd zijn.

Inhoudsopgave

  1. bcrypt_class.inc.php

Labels

Navigatie

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.