Domanda

Attualmente si dice che MD5 è parzialmente non sicuro. Tenendo conto di ciò, vorrei sapere quale meccanismo utilizzare per la protezione con password.

Questa domanda, Is & # 8220; doppio hashing & # 8221; una password meno sicura del semplice hashing una volta? suggerisce che l'hashing più volte può essere una buona idea, mentre Come implementare la protezione con password per i singoli file? suggerisce di usare salt.

Sto usando PHP. Voglio un sistema di crittografia password sicuro e veloce. Hashing di una password un milione di volte può essere più sicuro, ma anche più lento. Come raggiungere un buon equilibrio tra velocità e sicurezza? Inoltre, preferirei che il risultato avesse un numero costante di caratteri.

  1. Il meccanismo di hashing deve essere disponibile in PHP
  2. Deve essere sicuro
  3. Può usare il sale (in questo caso, tutti i sali sono ugualmente buoni? Esiste un modo per generare sali buoni?)

Inoltre, dovrei memorizzare due campi nel database (uno usando MD5 e un altro usando SHA, per esempio)? Lo renderebbe più sicuro o meno sicuro?

Nel caso in cui non fossi abbastanza chiaro, voglio sapere quali funzioni di hashing utilizzare e come scegliere un buon sale per avere un meccanismo di protezione con password sicuro e veloce.

Domande correlate che non coprono completamente la mia domanda:

Qual è la differenza tra SHA e MD5 in PHP
Crittografia password semplice
Metodi sicuri per la memorizzazione di chiavi, password per asp.net
Come implementeresti le password salate in Tomcat 5.5

È stato utile?

Soluzione

  

DISCLAIMER : questa risposta è stata scritta nel 2008.

     

Da allora, PHP ci ha fornito password_hash e password_verify e, poiché la loro introduzione, sono la password raccomandata hashing & amp; metodo di controllo.

     

La teoria della risposta è comunque una buona lettura.

TL; DR

cosa non fare

  • Non limitare quali caratteri gli utenti possono inserire per le password. Solo gli idioti lo fanno.
  • Non limitare la lunghezza di una password. Se i tuoi utenti desiderano una frase con supercalifragilisticexpialidocious, non impedire loro di usarla.
  • Non archiviare mai la password dell'utente in testo normale.
  • Non inviare mai una password via e-mail al tuo utente tranne quando ha perso la sua e tu ne hai inviata una temporanea.
  • Mai e poi mai registrare le password in alcun modo.
  • Non inserire mai le password con SHA1 o MD5 o persino SHA256! I cracker moderni possono superare 60 e 180 miliardi di hash / secondo (rispettivamente).
  • Non mescolare bcrypt e con raw output di hash () , usa l'output esadecimale o codifica base64. (Questo vale per qualsiasi input che può contenere un \ 0 canaglia, che può indebolire seriamente la sicurezza.)

Dos

  • Usa scrypt quando puoi; bcrypt se non puoi.
  • Usa PBKDF2 se non puoi usare bcrypt o scrypt, con hash SHA2.
  • Ripristina le password di tutti quando il database è compromesso.
  • Implementa una lunghezza minima ragionevole di 8-10 caratteri, oltre a richiedere almeno 1 lettera maiuscola, 1 lettera minuscola, un numero e un simbolo. Ciò migliorerà l'entropia della password, a sua volta rendendola più difficile da decifrare. (Vedi la sezione " Cosa rende una buona password? & Quot; per alcuni dibattiti.)

Perché comunque le password hash?

L'obiettivo dietro le password di hashing è semplice: impedire l'accesso dannoso agli account utente compromettendo il database. Quindi l'obiettivo dell'hash delle password è quello di scoraggiare un hacker o un cracker costando loro troppo tempo o denaro per calcolare le password in chiaro. E i tempi / i costi sono i migliori deterrenti nel tuo arsenale.

Un altro motivo per cui si desidera un hash valido e affidabile su un account utente è darti abbastanza tempo per cambiare tutte le password nel sistema. Se il tuo database è compromesso, avrai bisogno di tempo sufficiente per quantomeno bloccare il sistema, se non cambiare tutte le password nel database.

Jeremiah Grossman, CTO di Whitehat Security, ha dichiarato dichiarato sul suo blog dopo un recente recupero della password che ha richiesto la rottura della forza di protezione della password:

  

È interessante notare che, vivendo questo incubo, ho imparato MOLTO che non sapevo su cracking, archiviazione e complessità della password. Ho capito perché l'archiviazione delle password è molto più importante della complessità delle password. Se non sai come viene memorizzata la tua password, tutto ciò di cui puoi davvero fare affidamento è la complessità. Questa potrebbe essere una conoscenza comune di password e professionisti della crittografia, ma per l'esperto medio di InfoSec o Web Security, I ne dubito fortemente.

(Enfasi mia.)

Cosa rende comunque una buona password?

Entropy . (Non che sottoscrivo pienamente il punto di vista di Randall.)

In breve, l'entropia è la quantità di variazione all'interno della password. Quando una password è solo lettere latine minuscole, sono solo 26 caratteri. Questa non è molta variazione. Le password alfanumeriche sono migliori, con 36 caratteri. Ma consentire maiuscole e minuscole, con simboli, è di circa 96 caratteri. È molto meglio delle semplici lettere. Un problema è che per rendere memorabili le nostre password inseriamo schemi che riducono l'entropia. Oops!

L'entropia della password è approssimata facilmente . L'uso dell'intera gamma di caratteri ASCII (circa 96 caratteri tipizzabili) produce un'entropia di 6,6 per carattere, che a 8 caratteri per una password è ancora troppo bassa (52.679 bit di entropia) per la sicurezza futura. Ma la buona notizia è: password più lunghe e password con caratteri unicode aumentano davvero l'entropia di una password e rendono più difficile decifrare.

C'è una discussione più lunga sull'entropia della password nel Crypto StackExchange sito. Una buona ricerca su Google produrrà anche molti risultati.

Nei commenti che ho parlato con @popnoodles, che ha sottolineato che applicando una politica password di lunghezza X con X molte lettere, numeri, simboli, ecc., può effettivamente ridurre l'entropia creando lo schema password più prevedibile. Sono daccordo. La casualità, il più casuale possibile, è sempre la soluzione più sicura ma meno memorabile.

Per quanto ne so, fare la migliore password del mondo è un Catch-22. O non è memorabile, troppo prevedibile, troppo breve, troppi caratteri unicode (difficili da digitare su un dispositivo Windows / Mobile), troppo lunghi, ecc. Nessuna password è davvero abbastanza buona per i nostri scopi, quindi dobbiamo proteggerli come se fossero erano a Fort Knox.

Best practice

Bcrypt e scrypt sono le migliori pratiche attuali. Scrypt sarà meglio di bcrypt in tempo, ma non ha visto l'adozione come standard da Linux / Unix o dai server web e non ha ancora pubblicato recensioni approfondite sul suo algoritmo. Tuttavia, il futuro dell'algoritmo sembra promettente. Se lavori con Ruby c'è un scrypt gem che ti aiuterà, e Node.js ora ha il suo pacchetto scrypt . Puoi utilizzare Scrypt in PHP tramite l'estensione Scrypt o l'estensione estensione Libsodium (entrambi sono disponibili in PECL).

Consiglio vivamente di leggere la documentazione per la funzione cripta se vuoi capire come usare bcrypt, o trovarti un buono wrapper o usa qualcosa come PHPASS per un'implementazione più legacy. Raccomando un minimo di 12 round di bcrypt, se non da 15 a 18.

Ho cambiato idea sull'uso di bcrypt quando ho saputo che bcrypt utilizza solo il programma chiave di blowfish, con un meccanismo a costo variabile. Quest'ultimo consente di aumentare i costi per forzare una password in modo bruto aumentando il programma di chiavi già costoso di Blowfish.

Pratiche medie

Quasi non riesco più a immaginare questa situazione. PHPASS supporta PHP da 3.0.18 a 5.3, quindi è utilizzabile su quasi tutte le installazioni immaginabili & # 8212; e dovrebbe essere usato se non sai per certo che il tuo ambiente supporta bcrypt.

Ma supponi che non puoi usare bcrypt o PHPASS. E allora?

Prova a implementare PDKBF2 con il numero massimo di round che il tuo ambiente / applicazione / percezione dell'utente può tollerare. Il numero più basso che consiglierei è di 2500 colpi. Inoltre, assicurati di utilizzare hash_hmac () se è disponibile per rendere più difficile la riproduzione dell'operazione.

Pratiche future

L'arrivo in PHP 5.5 è una libreria completa di protezione password che consente di estrarre qualsiasi dolori di lavorare con bcrypt. Mentre la maggior parte di noi è bloccata con PHP 5.2 e 5.3 negli ambienti più comuni, in particolare gli host condivisi, @ircmaxell ha creato un livello di compatibilità per l'API in arrivo che è retrocompatibile con PHP 5.3.7.

Riepilogo crittografia & amp; Diniego

La potenza di calcolo richiesta per craccare in realtà non esiste una password con hash. L'unico modo per i computer di "crackare" una password è ricrearla e simulare l'algoritmo di hashing utilizzato per proteggerla. La velocità dell'hash è linearmente correlata alla sua capacità di essere forzata brutalmente. Peggio ancora, la maggior parte degli algoritmi di hash può essere facilmente parallelizzata per funzionare ancora più velocemente. Ecco perché schemi costosi come bcrypt e scrypt sono così importanti.

Non puoi prevedere tutte le minacce o le vie di attacco, quindi devi fare del tuo meglio per proteggere i tuoi utenti in anticipo . Altrimenti, potresti anche perdere il fatto di essere stato attaccato fino a quando non è troppo tardi ... e sei responsabile . Per evitare quella situazione, agire paranoico per cominciare. Attacca il tuo software (internamente) e tenta di rubare le credenziali dell'utente, o modificare gli account di altri utenti o accedere ai loro dati. Se non collaudi la sicurezza del tuo sistema, non puoi incolpare nessuno tranne te stesso.

Infine: non sono un crittografo. Qualunque cosa abbia detto è la mia opinione, ma mi capita di pensare che sia basato sul buon vecchio senso comune ... e su molte letture. Ricorda, sii il più paranoico possibile, rendi le cose più difficili da intromettere il più possibile, quindi, se sei ancora preoccupato, contatta un hacker o un crittografo dal cappello bianco per vedere cosa dicono del tuo codice / sistema.

Altri suggerimenti

Una risposta molto più breve e sicura - non scrivere affatto il tuo meccanismo di password , usa un meccanismo provato e testato.

  • PHP 5.5 o versioni successive: password_hash () è di buona qualità e parte del core di PHP.
  • Versioni precedenti di PHP: la libreria phpass di OpenWall è molto meglio della maggior parte del codice personalizzato, utilizzato in WordPress, Drupal, ecc.

La maggior parte dei programmatori non ha le competenze per scrivere codice relativo alla crittografia in modo sicuro senza introdurre vulnerabilità.

Autotest rapido: che cos'è l'estensione della password e quante iterazioni dovresti usare? Se non conosci la risposta, dovresti usare password_hash () , poiché l'estensione della password è ora una caratteristica fondamentale dei meccanismi delle password a causa di CPU molto più veloci e l'uso di GPU e FPGA per decifrare le password a velocità miliardi di ipotesi al secondo (con GPU).

Ad esempio, puoi decifrare tutte le password di Windows a 8 caratteri in 6 ore utilizzando 25 GPU installate in 5 PC desktop. Si tratta di forzare brutalmente, ad esempio enumerare e controllare ogni password di Windows di 8 caratteri , inclusi i caratteri speciali, e non è un attacco di dizionario. Era il 2012, a partire dal 2018 potresti usare meno GPU o crackare più velocemente con 25 GPU.

Ci sono anche molti attacchi di tabelle arcobaleno su password di Windows che girano su CPU ordinarie e sono molto veloci. Tutto questo perché Windows continua non salare o allungare le sue password, anche in Windows 10 - non fare lo stesso errore di Microsoft!

Vedi anche:

  • risposta eccellente con ulteriori informazioni su perché password_hash () o phpass sono il modo migliore di procedere.
  • buon articolo di blog che fornisce 'fattori di lavoro' raccomandati (numero di iterazioni) per gli algoritmi principali tra cui bcrypt, scrypt e PBKDF2.

Non memorizzerei la password con hash in due modi diversi, perché il sistema è almeno debole come il più debole degli algoritmi di hash in uso.

A partire da PHP 5.5, PHP ha funzioni semplici e sicure per l'hashing e la verifica delle password, password_hash () e password_verify ()

$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false

Quando si utilizza password_hash () , genera un salt casuale e lo include nell'hash emesso (insieme al costo e all'algoritmo utilizzati.) password_verify () quindi legge tale hash e determina il metodo salt e di crittografia utilizzato e lo verifica rispetto alla password di testo in chiaro fornita.

Fornendo il PASSWORD_DEFAULT viene indicato a PHP di utilizzare l'algoritmo di hashing predefinito della versione installata di PHP. Quale algoritmo significa che è destinato a cambiare nel tempo nelle versioni future, in modo che sia sempre uno dei più potenti algoritmi disponibili.

L'aumento dei costi (il cui valore predefinito è 10) rende l'hash più difficile da forzare, ma significa anche generare hash e verificare le password contro di loro sarà più lavoro per la CPU del tuo server.

Nota che anche se l'algoritmo di hashing predefinito può cambiare, i vecchi hash continueranno a verificarsi bene perché l'algoritmo utilizzato è archiviato nell'hash e password_verify () lo riprende.

Sebbene alla domanda sia stata data una risposta, voglio solo ribadire che i sali usati per l'hash dovrebbero essere casuali e non come l'indirizzo e-mail come suggerito nella prima risposta.

Ulteriori spiegazioni sono disponibili su- http: / /www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

  

Di recente ho discusso se gli hash delle password sono stati salati in modo casuale   i bit sono più sicuri di quello salato con indovinabile o noto   sali. Vediamo: se il sistema che memorizza la password è compromesso come   così come il sistema che immagazzina il sale casuale, l'attaccante lo farà   avere accesso all'hash e al sale, quindi se il sale è casuale o   no, non importa. L'attaccante può generare pre-calcolato   tavoli arcobaleno per rompere l'hash. Ecco che arriva la parte interessante   non è così banale generare tabelle pre-calcolate. Facciamo un esempio   del modello di sicurezza WPA. La tua password WPA in realtà non viene mai inviata a   Punto di accesso wireless. Invece, è hash con il tuo SSID (il   nome di rete come Linksys, Dlink ecc.). Un'ottima spiegazione di come   questo funziona è qui. Per recuperare la password dall'hash, lo farai   è necessario conoscere la password e salt (nome della rete). Chiesa di   Wifi ha già pre-calcolate tabelle hash che hanno i migliori 1000 SSID e   circa 1 milione di password. La dimensione è di tutti i tavoli è di circa 40 GB.   Come puoi leggere sul loro sito, qualcuno ha usato 15 array FGPA per 3 giorni   per generare queste tabelle. Supponendo che la vittima stia utilizzando l'SSID come   & # 8220; & # 8243 a387csf3; e la password come & # 8220; 123456 & # 8243 ;, saranno violate da quelli   tavoli? No! .. non può. Anche se la password è debole, le tabelle   non hai hash per SSID a387csf3. Questa è la bellezza di avere   sale casuale. Deterrerà i cracker che prosperano su pre-calcolati   tabelle. Può fermare un determinato hacker? Probabilmente no. Ma usando   i sali casuali forniscono un ulteriore livello di difesa. Mentre siamo attivi   questo argomento, parliamo di un ulteriore vantaggio della memorizzazione casuale   sali su un sistema separato. Scenario n. 1: gli hash delle password sono memorizzati   sul sistema X e i valori di sale utilizzati per l'hash sono memorizzati sul sistema Y.   Questi valori salt sono ipotizzabili o noti (ad es. Nome utente) Scenario n. 2:   Gli hash delle password sono memorizzati sul sistema X e i valori salt utilizzati per   gli hash sono memorizzati sul sistema Y. Questi valori di salt sono casuali. Nel caso   il sistema X è stato compromesso, come puoi immaginare, c'è un enorme   vantaggio dell'utilizzo di sale casuale su un sistema separato (scenario n. 2).   L'attaccante dovrà indovinare i valori di addizione per riuscire a decifrare   hash. Se si utilizza un sale a 32 bit, 2 ^ 32 = 4.294.967.296 (circa 4.2   miliardi) possono essere richieste iterazioni per ogni password indovinata.

Voglio solo sottolineare che PHP 5.5 include una API di hashing della password che fornisce un wrapper intorno a crypt () . Questa API semplifica notevolmente l'attività di hashing, verifica e rehashing degli hash delle password. L'autore ha anche rilasciato un pacchetto di compatibilità (sotto forma di un singolo file password.php che semplicemente richiede da utilizzare), per coloro che utilizzano PHP 5.3.7 e versioni successive e desiderano utilizzarlo subito.

Supporta solo BCRYPT per ora, ma mira ad essere facilmente esteso per includere altre tecniche di hashing delle password e poiché la tecnica e il costo sono memorizzati come parte dell'hash, le modifiche alla tua tecnica / costo di hashing preferito non invalideranno gli hash correnti , il framework utilizzerà automagicamente, durante la convalida, utilizzerà la tecnica / i costi corretti. Gestisce anche la generazione di un "sicuro". salt se non definisci esplicitamente il tuo.

L'API espone quattro funzioni:

  • password_get_info () - restituisce informazioni sull'hash specificato
  • password_hash () - crea un hash password
  • password_needs_rehash () : controlla se l'hash specificato corrisponde alle opzioni fornite. Utile per verificare se l'hash è conforme alla tua attuale tecnica / schema dei costi che ti consente di ripassare se necessario
  • password_verify () - verifica che una password corrisponda a un hash

Al momento queste funzioni accettano le costanti password PASSWORD_BCRYPT e PASSWORD_DEFAULT, che al momento sono sinonimi, con la differenza che PASSWORD_DEFAULT "può cambiare nelle versioni PHP più recenti quando sono supportati algoritmi di hashing più recenti e più potenti. " L'uso di PASSWORD_DEFAULT e password_needs_rehash () all'accesso (e, se necessario, ripassare) dovrebbe garantire che gli hash siano ragionevolmente resistenti agli attacchi di forza bruta con poco o nessun lavoro per te.

EDIT: ho appena capito che questo è menzionato brevemente nella risposta di Robert K. Lascerò questa risposta qui poiché penso che fornisca un po 'più di informazioni su come funziona e sulla facilità d'uso che fornisce a chi non conosce la sicurezza.

Sto usando Phpass che è una semplice classe PHP a un file che potrebbe essere implementata molto facilmente in quasi tutti i PHP progetto. Vedi anche La H .

Per impostazione predefinita, utilizzava la crittografia più potente disponibile implementata in Phpass, che è bcrypt e ricorre ad altre crittografie fino a MD5 per fornire la compatibilità con le versioni precedenti di framework come Wordpress.

L'hash restituito potrebbe essere archiviato nel database così com'è. L'uso di esempio per generare l'hash è:

$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

Per verificare la password, è possibile utilizzare:

$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);

THINGS TO REMEMBER

A lot has been said about Password encryption for PHP, most of which is very good advice, but before you even start the process of using PHP for password encryption make sure you have the following implemented or ready to be implemented.

SERVER

PORTS

No matter how good your encryption is if you don't properly secure the server that runs the PHP and DB all your efforts are worthless. Most servers function relatively the same way, they have ports assigned to allow you to access them remotely either through ftp or shell. Make sure that you change the default port of which ever remote connection you have active. By not doing this you in effect have made the attacker do one less step in accessing your system.

USERNAME

For all that is good in the world do not use the username admin, root or something similar. Also if you are on a unix based system DO NOT make the root account login accessible, it should always be sudo only.

PASSWORD

You tell your users to make good passwords to avoid getting hacked, do the same. What is the point in going through all the effort of locking your front door when you have the backdoor wide open.

DATABASE

SERVER

Ideally you want your DB and APPLICATION on separate servers. This is not always possible due to cost, but it does allow for some safety as the attacker will have to go through two steps to fully access the system.

USER

Always have your application have its own account to access the DB, and only give it the privileges it will need.

Then have a separate user account for you that is not stored anywhere on the server, not even in the application.

Like always DO NOT make this root or something similar.

PASSWORD

Follow the same guidelines as with all good passwords. Also don't reuse the same password on any SERVER or DB accounts on the same system.

PHP

PASSWORD

NEVER EVER store a password in your DB, instead store the hash and unique salt, I will explain why later.

HASHING

ONE WAY HASHING!!!!!!!, Never hash a password in a way that it can be reversed, Hashes should be one way, meaning you don't reverse them and compare them to the password, you instead hash the entered password the same way and compare the two hashes. This means that even if an attacker gets access to the DB he doesn't know what the actually password is, just its resulting hash. Which means more security for your users in the worst possible scenario.

There are a lot of good hashing functions out there (password_hash, hash, etc...) but you need to select a good algorithm for the hash to be effective. (bcrypt and ones similar to it are decent algorithms.)

When hashing speed is the key, the slower the more resistant to Brute Force attacks.

One of the most common mistakes in hashing is that hashes are not unique to the users. This is mainly because salts are not uniquely generated.

SALTING

Passwords should always be salted before hashed. Salting adds a random string to the password so similar passwords don't appear the same in the DB. However if the salt is not unique to each user (ie: you use a hard coded salt) than you pretty much have made your salt worthless. Because once an attacker figures out one password salt he has the salt for all of them.

When you create a salt make sure it is unique to the password it is salting, then store both the completed hash and salt in your DB. What this will do is make it so that an attacker will have to individually crack each salt and hash before they can gain access. This means a lot more work and time for the attacker.

USERS CREATING PASSWORDS

If the user is creating a password through the frontend that means it has to be sent to the server. This opens up a security issue because that means the unencrypted password is being sent to the server and if a attacker is able to listen and access that all your security in PHP is worthless. ALWAYS transmit the data SECURELY, this is done through SSL, but be weary even SSL is not flawless (OpenSSL's Heartbleed flaw is an example of this).

Also make the user create a secure password, it is simple and should always be done, the user will be grateful for it in the end.

Finally, no matter the security measures you take nothing is 100% secure, the more advanced the technology to protect becomes the more advanced the attacks become. But following these steps will make your site more secure and far less desirable for attackers to go after.

Here is a PHP class that creates a hash and salt for a password easily

http://git.io/mSJqpw

Google says SHA256 is available to PHP.

You should definitely use a salt. I'd recommend using random bytes (and not restrict yourself to characters and numbers). As usually, the longer you choose, the safer, slower it gets. 64 bytes ought to be fine, i guess.

I found perfect topic on this matter here: https://crackstation.net/hashing-security.htm, I wanted you to get benefit from it, here is source code also that provided prevention against time-based attack also.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

In the end, double-hashing, mathematically, provides no benefit. In practice, however, it is useful for preventing rainbow table-based attacks. In other words, it is of no more benefit than hashing with a salt, which takes far less processor time in your application or on your server.

I usually use SHA1 and salt with the user ID (or some other user-specific piece of information), and sometimes I additionally use a constant salt (so I have 2 parts to the salt).

SHA1 is now also considered somewhat compromised, but to a far lesser degree than MD5. By using a salt (any salt), you're preventing the use of a generic rainbow table to attack your hashes (some people have even had success using Google as a sort of rainbow table by searching for the hash). An attacker could conceivably generate a rainbow table using your salt, so that's why you should include a user-specific salt. That way, they will have to generate a rainbow table for each and every record in your system, not just one for your entire system! With that type of salting, even MD5 is decently secure.

SHA1 and a salt should suffice (depending, naturally, on whether you are coding something for Fort Knox or a login system for your shopping list) for the foreseeable future. If SHA1 isn't good enough for you, use SHA256.

The idea of a salt is to throw the hashing results off balance, so to say. It is known, for example, that the MD5-hash of an empty string is d41d8cd98f00b204e9800998ecf8427e. So, if someone with good enough a memory would see that hash and know that it's the hash of an empty string. But if the string is salted (say, with the string "MY_PERSONAL_SALT"), the hash for the 'empty string' (i.e. "MY_PERSONAL_SALT") becomes aeac2612626724592271634fb14d3ea6, hence non-obvious to backtrace. What I'm trying to say, that it's better to use any salt, than not to. Therefore, it's not too much of an importance to know which salt to use.

There are actually websites that do just this - you can feed it a (md5) hash, and it spits out a known plaintext that generates that particular hash. If you would get access to a database that stores plain md5-hashes, it would be trivial for you to enter the hash for the admin to such a service, and log in. But, if the passwords were salted, such a service would become ineffective.

Also, double-hashing is generally regarded as bad method, because it diminishes the result space. All popular hashes are fixed-length. Thus, you can have only a finite values of this fixed length, and the results become less varied. This could be regarded as another form of salting, but I wouldn't recommend it.

ok in the fitsy we need salt salt must be unique so let generate it

   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }

also we need the hash I`m using sha512 it is the best and it is in php

   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }

so now we can use this functions to generate safe password

// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);

now we need to save in database our $hash_psw variable value and $salt variable

and for authorize we will use same steps...

it is the best way to safe our clients passwords...

P.s. for last 2 steps you can use your own algorithm... but be sure that you can generate this hashed password in the future when you need to authorize user...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top