Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[php/mysql] Wachtwoord encryptie voor gebruikers/leden

Pagina: 1
Acties:

  • Saven
  • Registratie: December 2006
  • Laatst online: 20:24

Saven

Administrator

Topicstarter
Goedeavond ;)

Ik ben al jaren bezig met het maken van systemen/systeempjes in PHP i.c.m. MySQL. Nu is het zo dat vroeger md5 hashing de standaard was voor password encryption, maar niet veel later was dat al sha1.

Nu heb ik een lange tijd geen systemen meer gemaakt waarbij er een database tabel komt met gegevens van leden. Omdat je de laatste tijd steeds meer leest over het goed encrypten van passwords ben ik me hier natuurlijk weer in gaan verdiepen. Eigenlijk komt daar dus uit naar voren dat bcrypt op basis van blowfish tegenwoordig de standaard moet zijn.

Hier moet je een salt bij opgeven als je een plaintext wachtwoord wil encrypten. Nu is dat op zich logisch, maar ik zit een beetje dubbel met de implementatie hiervan. Ik zie in de meeste (eigenlijk alle) voorbeelden dat de salt per gebruiker anders is, maar die salt moet dan ook in de database worden opgeslagen.

Feitelijk zit je dan met zoiets:
PHP:
1
2
3
4
$random = randomstring22tekens();

$salt = '$2y$07$'.$random.'$';
$encrypted = crypt("passwordtext", $salt);


Dus voor zover ik begrijp sla je de $salt en de $encrypted op in je database.

Aangezien het juist de database is, die het meest wordt binnengedrongen door hackers, is het dan niet verstandig om de hash te hardcoden in je source? Dan heb je 1 salt voor iedereen, maar in theorie maakt dat niks uit omdat als iemand toegang heeft in de database, hij/zij toch al de hash heeft.

Iemand die hier ook een mening over heeft? :)

  • Pizzalucht
  • Registratie: Januari 2011
  • Laatst online: 22:08

Pizzalucht

Snotneus.

Het gaat erom dat er geen rainbow tables kunnen worden gemaakt.

Doordat je voor elke user een andere salt hebt, zullen ze voor elke user een rainbow table moeten maken, dat heeft dan dus geen zin meer.

Wat je ook kan doen is een salt genereren op basis van de username van de user, maar het beste zou zijn om gewoon een unieke salt te genereren en die op te slaan bij de password hash.

  • RedHat
  • Registratie: Augustus 2000
  • Laatst online: 21-11 18:12
Hardcoded + random salt is wel zo veilig. Hebben ze je db dan hebben ze weinig aan rainbow tables. Bij een salt van een veld in de db kunnen ze natuurlijk een rainbow table maken die elk veld test.

[ Voor 33% gewijzigd door RedHat op 20-02-2013 22:32 ]


  • Sleepkever
  • Registratie: Juni 2007
  • Laatst online: 22-11 00:12
Als je het echt goed gedaan wilt hebben pak je gewoon een van de bestaande oplossingen. Zoals deze:
http://www.openwall.com/phpass/
2 functies, hashpassword en checkpassword. De salt wordt random gegenereerd en bij het password opgeslagen. Hele simpele uitleg hoe je het in je php applicatie kan gebruiken staat hier.

Uitleg over hoe het nou allemaal werkt en zeker de moeite waard om te lezen als je benieuwd bent hoe je passwords nu echt veilig op kan slaan staat hier.

Random salt per gebruiker is eigenlijk al genoeg om rainbow tables tegen te gaan. Het loont immers niet om per gebruiker een rainbow table aan te gaan maken. Dan is het hele nut van rainbow tables weg en is het sneller om brute force te gaan werken. Ofwel, niet interessant meer als je binnen een jaar of 10 een password terug verwacht. Dictionary attacks zouden nog wel kunnen, maar die zal je (anders dan gebruikers te instrueren goeie passwords te gebruiken) toch niet tegen gaan als je database gejat is.

[ Voor 30% gewijzigd door Sleepkever op 20-02-2013 22:55 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

RedHat schreef op woensdag 20 februari 2013 @ 22:30:
Hardcoded + random salt is wel zo veilig. Hebben ze je db dan hebben ze weinig aan rainbow tables. Bij een salt van een veld in de db kunnen ze natuurlijk een rainbow table maken die elk veld test.
Precies verkeerd om. Als elke gebruiker een andere salt heeft is het niet mogelijk om een rainbow table te maken voor die database maar zal er per gebruiker gebruteforced moeten worden. De hele essentie van een rainbow table is dat voor iedere gebruiker dezelfde hashing gebruikt wordt. De aanvaller maakt dan gewoon 1 grote lijst met gehashde wachtwoorden en kan vervolgens die ene lijst tegen alle buitgemaakte wachtwoorden houden.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Martijn19
  • Registratie: Februari 2012
  • Laatst online: 28-07 12:47
Janoz schreef op donderdag 21 februari 2013 @ 10:15:
[...]

Precies verkeerd om. Als elke gebruiker een andere salt heeft is het niet mogelijk om een rainbow table te maken voor die database maar zal er per gebruiker gebruteforced moeten worden. De hele essentie van een rainbow table is dat voor iedere gebruiker dezelfde hashing gebruikt wordt. De aanvaller maakt dan gewoon 1 grote lijst met gehashde wachtwoorden en kan vervolgens die ene lijst tegen alle buitgemaakte wachtwoorden houden.
Inderdaad, dit is wel eens een lastig punt als je iemand iets over password hashing probeert uit te leggen ("waarom zet je de hash ook in de database dan?").

  • Saven
  • Registratie: December 2006
  • Laatst online: 20:24

Saven

Administrator

Topicstarter
Bedankt voor de insights :) Dan lijkt het me het verstandigst om alleen de random string van 22 tekens in de database op te slaan, ipv de gehele salt? :)

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 20:57

Matis

Rubber Rocket

Ik heb ooit een tutorial gevolgd waarin ook het hashen en valideren van gehashte wachtwoorden aan bod kwam.
Ik heb daarvoor de volgende twee functies
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    private function validatePassword($password, $is_hashed = false)
    {
        if ($is_hashed === false)
        {
            $salt = substr($this->hashed_password, 0, 64);
            $hash = substr($this->hashed_password, 64, 64);
            $password_hash = hash('sha256', $salt . $password);
            return $password_hash === $hash;
        }
        return $password === $this->hashed_password;
    }

    private function hashPassword($password)
    {
        $salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
        $hash = hash('sha256', $salt . $password);

        return $salt . $hash;
    }

Reserveer in je database 128 karakters voor het wachtwoord. De eerste 64 bytes is het gehashte wachtwoord. Het tweede de salt.

Ik moet overigens bekennen dat ik deze functies alleen gebruik voor inhouse tooltjes en ik weet ook niet of er veilige / betere methodes zijn.

If money talks then I'm a mime
If time is money then I'm out of time


  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 21:50
Je kan ook de standaard PHP (5.5) manier gebruiken, backwards compatible door: https://github.com/ircmaxell/password_compat
Dan hoef je alleen maar te doen:
PHP:
1
2
3
4
5
6
7
8
9
//Hash
$hash = password_hash($password, PASSWORD_BCRYPT);

//Verify
if (password_verify($password, $hash)) {
    /* Valid */
} else {
    /* Invalid */
}
Saven schreef op donderdag 21 februari 2013 @ 12:19:
Bedankt voor de insights :) Dan lijkt het me het verstandigst om alleen de random string van 22 tekens in de database op te slaan, ipv de gehele salt? :)
Je krijgt als $hash gewoon een string waarin de gebruikte methode + salt + hash in staat. Die heb je ook weer nodig om te controleren of de hash klopt. Gewoon in zijn geheel opslaan dus. Als je later je hash sterker wil maken, moet je wel kunnen controleren wat de huidige methode is.

[ Voor 44% gewijzigd door Barryvdh op 21-02-2013 14:36 ]

Pagina: 1