Sök…


Introduktion

Eftersom säkrare webbtjänster undviker att lagra lösenord i vanlig textformat, erbjuder språk som PHP olika (okrypterbara) hashfunktioner för att stödja den säkrare industristandarden. Det här ämnet ger dokumentation för korrekt hashing med PHP.

Syntax

  • string password_hash ( string $password , integer $algo [, array $options ] )
  • boolean password_verify ( string $password , string $hash )
  • boolean password_needs_rehash ( string $hash , integer $algo [, array $options ] )
  • array password_get_info ( string $hash )

Anmärkningar

Innan PHP 5.5 kan du använda kompatibilitetspaketet för att tillhandahålla password_* -funktionerna. Det rekommenderas starkt att du använder kompatibilitetspaketet om du kan göra det.

Med eller utan kompatibilitetspaketet, korrigerar Bcrypt-funktionalitet via crypt() förlitar sig på PHP 5.3.7+, annars måste du begränsa lösenord till ASCII-teckenuppsättningar.

Obs! Om du använder PHP 5.5 eller senare använder du en version som inte stöds av PHP som inte längre får några säkerhetsuppdateringar. Uppdatera så snart som möjligt, du kan uppdatera ditt lösenord hash efteråt.

Algoritmval

Säkra algoritmer

Osäkra algoritmer

Följande hashningsalgoritmer är osäkra eller olämpliga för syfte och bör därför inte användas . De var aldrig lämpade för hashning av lösenord, eftersom de är utformade för snabba smälter istället för långsam och svår att brute kraft lösenord hash.

Om du använder någon av dem , även inklusive salter, bör du byta till en av de rekommenderade säkra algoritmerna så snart som möjligt .

Algoritmer anses vara osäkra:

Vissa algoritmer kan på ett säkert sätt användas som algoritmer för meddelandetillförsel för att bevisa äkthet, men aldrig som algoritmer för hashing-lösenord :

  • SHA-2
  • SHA-3

Observera att starka hascher som SHA256 och SHA512 är obrutna och robusta, men det är i allmänhet säkrare att använda bcrypt- eller argon2- hashfunktioner eftersom brute-kraftattacker mot dessa algoritmer är mycket svårare för klassiska datorer.

Bestäm om ett befintligt lösenord hash kan uppgraderas till en starkare algoritm

Om du använder PASSWORD_DEFAULT metoden för att låta systemet välja den bästa algoritmen att hash dina lösenord med, eftersom standardinställningen ökar i styrka kanske du vill omväxla gamla lösenord när användare loggar in

<?php
// first determine if a supplied password is valid
if (password_verify($plaintextPassword, $hashedPassword)) {

    // now determine if the existing hash was created with an algorithm that is
    // no longer the default
    if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {

        // create a new hash with the new default
        $newHashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT);

        // and then save it to your data store
        //$db->update(...);
    }
}
?>

Om lösenord_funktionerna inte är tillgängliga på ditt system (och du inte kan använda kompatibilitetspaketet länkat i kommentarerna nedan) kan du bestämma algoritmen och använda för att skapa den ursprungliga hash på en metod som liknar följande:

<?php
if (substr($hashedPassword, 0, 4) == '$2y$' && strlen($hashedPassword) == 60) {
    echo 'Algorithm is Bcrypt';
    // the "cost" determines how strong this version of Bcrypt is
    preg_match('/\$2y\$(\d+)\$/', $hashedPassword, $matches);
    $cost = $matches[1];
    echo 'Bcrypt cost is '.$cost;
}
?>

Skapa ett lösenord hash

Skapa lösenord hash med password_hash() att använda den nuvarande branschen för bästa praktik-hash eller nyckeldivation. I skrivande stund är standarden bcrypt , vilket innebär att PASSWORD_DEFAULT innehåller samma värde som PASSWORD_BCRYPT .

$options = [
    'cost' => 12,
];

$hashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT, $options);

Den tredje parametern är inte obligatorisk .

Värdet 'cost' bör väljas baserat på din produktionsserver hårdvara. Att öka det kommer att göra lösenordet dyrare att generera. Ju dyrare det är att generera desto längre tid tar det någon som försöker knäcka den att generera den också. Kostnaden bör idealiskt vara så hög som möjligt, men i praktiken bör den ställas in så att den inte bromsar allt för mycket. Någonstans mellan 0,1 och 0,4 sekunder skulle det vara okej. Använd standardvärdet om du är osäker.

5,5

På PHP lägre än 5.5.0 är password_* inte tillgängliga. Du bör använda kompatibilitetspaketet för att ersätta dessa funktioner. Lägg märke till att kompatibilitetspaketet kräver PHP 5.3.7 eller högre eller en version som har $2y fixet tillbaka i det (som RedHat tillhandahåller).

Om du inte kan använda dessa kan du implementera lösenord hashing med crypt() Eftersom password_hash() är implementerat som ett omslag runt funktionen crypt() behöver du inte förlora någon funktionalitet.

// this is a simple implementation of a bcrypt hash otherwise compatible
// with `password_hash()`
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation

// if `CRYPT_BLOWFISH` is 1, that means bcrypt (which uses blowfish) is available
// on your system
if (CRYPT_BLOWFISH == 1) {
    $salt = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
    $salt = base64_encode($salt);
    // crypt uses a modified base64 variant
    $source = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    $dest = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt = strtr(rtrim($salt, '='), $source, $dest);
    $salt = substr($salt, 0, 22);
    // `crypt()` determines which hashing algorithm to use by the form of the salt string
    // that is passed in
    $hashedPassword = crypt($plaintextPassword, '$2y$10$'.$salt.'$');
}

Salt för lösenord hash

Trots pålitlighet hos kryptalgoritmen finns det fortfarande sårbarhet mot regnbågens bord . Det är anledningen, varför det rekommenderas att använda salt .

Ett salt är något som läggs till i lösenordet innan hashing för att göra källsträngen unik. Med två identiska lösenord kommer de resulterande hasherna också att vara unika eftersom deras salter är unika.

Ett slumpmässigt salt är en av de viktigaste delarna av ditt lösenordssäkerhet. Detta innebär att även med en uppslagstabell med kända lösenord hascher kan en angripare inte matcha din användares lösenord hash med databaslösenord hash eftersom ett slumpmässigt salt har använts. Du bör alltid använda slumpmässiga och kryptografiskt säkra salter. Läs mer

Med password_hash() bcrypt algoritm lagras vanlig textsalt tillsammans med den resulterande hash, vilket innebär att hash kan överföras över olika system och plattformar och fortfarande matchas mot det ursprungliga lösenordet.

7,0

Även när detta motverkas, kan du använda salt möjlighet att definiera din egen random salt.

 $options = [
        'salt' => $salt, //see example below
 ];

Viktigt . Om du utelämnar detta alternativ kommer ett slumpmässigt salt att genereras av password_hash () för varje lösenord hashed. Detta är det avsedda driftsläget.

7,0

Saltalternativet har avskrivits från och med PHP 7.0.0. Det är nu föredraget att helt enkelt använda saltet som genereras som standard.

Verifierar ett lösenord mot en hash

password_verify() är den inbyggda funktionen som tillhandahålls (från och med PHP 5.5) för att verifiera giltigheten av ett lösenord mot en känd hash.

<?php
if (password_verify($plaintextPassword, $hashedPassword)) {
    echo 'Valid Password';
}
else {
    echo 'Invalid Password.';
}
?>

Alla stötta hashalgoritmer lagrar information som identifierar vilken hash som användes i själva hash, så det finns inget behov att ange vilken algoritm du använder för att koda klartextlösenordet med.

Om lösenord_funktionerna inte är tillgängliga på ditt system (och du inte kan använda kompatibilitetspaketet som är länkat i kommentarerna nedan) kan du implementera lösenordsverifiering med funktionen crypt() . Observera att specifika försiktighetsåtgärder måste vidtas för att undvika timingattacker .

<?php
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation
if (CRYPT_BLOWFISH == 1) {
    // `crypt()` discards all characters beyond the salt length, so we can pass in
    // the full hashed password
    $hashedCheck = crypt($plaintextPassword, $hashedPassword);

    // this a basic constant-time comparison based on the full implementation used
    // in `password_hash()`
    $status = 0;
    for ($i=0; $i<strlen($hashedCheck); $i++) {
        $status |= (ord($hashedCheck[$i]) ^ ord($hashedPassword[$i]));
    }

    if ($status === 0) {
        echo 'Valid Password';
    }
    else {
        echo 'Invalid Password';
    }
}
?>


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow