Lengte van salt

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Wouter Van Marrum

Wouter Van Marrum

01/11/2014 19:23:40
Quote Anchor link
Hallo iedereen,

Ik ben bezig met het maken van een installatie script voor mijn systeem.
Nu wil ik dat de gebruiker een salt ( secret_key ) invoerd voordat de installatie voldaan kan worden,
Dit ivm met het hashen voor wachtwoord en het encrypten en decrypten voor bepaalde onderdelen.

Maar nu wil ik weten wat een goede lengte zal zijn.
Heb zelf in me hoofd een lengte van 15 tot 20 characters maar kwam op stackoverflow en het topic van ward hier dat het zo lang mogelijk moet zijn zodat het uniek is.

Kan iemand mij uitleggen welke lengte echt optimaal is en waarom.
Begin AUB niet over het hashen zelf daar gebruik ik password_hash voor !

M.V.G,
Wouter.
 
PHP hulp

PHP hulp

12/04/2021 00:47:03
 
Ward van der Put
Moderator

Ward van der Put

01/11/2014 19:42:48
Quote Anchor link
Wouter Van Marrum op 01/11/2014 19:23:40:
Heb zelf in me hoofd een lengte van 15 tot 20 characters maar kwam op stackoverflow en het topic van ward hier dat het zo lang mogelijk moet zijn zodat het uniek is.

Correct. De salt moet "wereldwijd" uniek zijn, zodat de salt slechts dat ene wachtwoord in de ene database beveiligt.

Langere salts zijn dus inderdaad beter. Maar vergeet vooral ook de diepte niet: het maakt nogal uit of je alleen de karakterset A..Z gebruikt of daaraan ook a..z en 0..9 of de volledige UTF-8 karakterset toevoegt.
 
Wouter Van Marrum

Wouter Van Marrum

01/11/2014 20:05:16
Quote Anchor link
Hallo ward,

Ik gebruik nu deze code om de salt te laten genereren als men dit wil :
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]};:'\"\|,<.>/?";
    var returnField = field;
    var secretLength = length;

    for( var i=0; i < secretLength; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    
    return $(returnField).val(text);


Als je verbeteringen weet hierop wil ik ze graag weten :)
 
Ward van der Put
Moderator

Ward van der Put

01/11/2014 20:16:46
Quote Anchor link
Regel 99 en 101 hieronder leveren veel meer karakters op dan regel 103 (die lijkt op jouw regel 2).

Verder heb ik de default lengte op 255 gezet, zodat de salt in een CHAR(255) past.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?php
namespace System\Security;

/**
 * Salt
 *
 * @author    Ward van der Put <Ward.van.der.Put@gmail.com>
 * @copyright Copyright (c) 2014 NewCo
 * @license   http://www.gnu.org/licenses/gpl.html GPLv3
 * @version   0.1.0
 */

final class Salt
{
    /**
     * @param string VERSION
     *     Semantic version (SemVer)
     */

    const VERSION = '0.1.0';

    /**
     * @param integer $Length
     *     String length of the salt (default 255).
     */

    private $Length = 255;

    /**
     * @param string $Salt
     *     String containing the random salt.
     */

    private $Salt;

    /**
     * Constructor
     *
     * @param integer $length
     *     The length of the desired salt string.  This must be a positive
     *     integer.  Defaults to 255 for a VARCHAR(255) or CHAR(255) column
     *     in MySQL.
     */

    public function __construct($length = 255)
    {

        $this->setLength($length);
        $this->randomize();
    }


    /**
     * Return the salt object as a string.
     *
     * @param void
     * @return string
     */

    public function __toString()
    {

        return $this->get();
    }


    /**
     * Get the salt string.
     *
     * @param void
     * @return string
     */

    public function get()
    {

        return $this->Salt;
    }


    /**
     * Get the salt string length.
     *
     * @param void
     * @return integer
     */

    public function getLength()
    {

        return $this->Length;
    }


    /**
     * Alias of randomize()
     *
     * @see randomize()
     */

    public function randomise()
    {

        $this->randomize();
        return $this;
    }


    /**
     * Generate or regenerate a random salt.
     *
     * @param void
     * @return $this
     */

    public function randomize()
    {

        if (function_exists('openssl_random_pseudo_bytes')) {
            $chars = openssl_random_pseudo_bytes($this->Length);
        }
elseif (function_exists('mcrypt_create_iv')) {
            $chars = mcrypt_create_iv($this->Length, MCRYPT_DEV_URANDOM);
        }
else {
            $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        }


        $salt = (string)null;
        $size = strlen($chars);
        for ($i = 0; $i < $this->Length; $i++) {
            $salt .= $chars[mt_rand(0, $size - 1)];
        }

        $this->Salt = $salt;
        
        return $this;
    }


    /**
     * Set the salt string length.
     *
     * @param integer $length
     *     The length of the salt string.  This must be a positive integer.
     *     PHP will try to cast this parameter to a non-null integer to use it.
     *
     * @return $this
     */

    public function setLength($length)
    {

        $this->Length = (int)$length;
        return $this;
    }
}
[
/code]
 
Wouter Van Marrum

Wouter Van Marrum

01/11/2014 21:14:57
Quote Anchor link
Hallo ward,

Dankjewel voor je voorbeeld hoe jij het doet.

Nu snap ik natuurlijk hoe langer, hoe unieker je salt is maar mij lijkt 255 beetje overkill.
Natuurlijk ben ik geen beveiliging expert maar waarom adviseer jij dan 255 ?

En zou jij het alleen via php doen of maakt het voor jouw niks uit dat ik het hier bijvoorbeeld met javascript doe ?
Zou je kunnen toelichten waarom ?
 
Ward van der Put
Moderator

Ward van der Put

01/11/2014 21:38:29
Quote Anchor link
Wouter Van Marrum op 01/11/2014 21:14:57:
Nu snap ik natuurlijk hoe langer, hoe unieker je salt is maar mij lijkt 255 beetje overkill.
Natuurlijk ben ik geen beveiliging expert maar waarom adviseer jij dan 255 ?

Waarom denk je dat het overkill is?

Het maakt in performance niets uit, dus dan ga je voor de langste en sterkste salt die je "gratis" of "voor dezelfde prijs" kunt krijgen.

Wouter Van Marrum op 01/11/2014 21:14:57:
Natuurlijk ben ik geen beveiliging expert maar waarom adviseer jij dan 255 ?

Langer is beter.
Nog langer is nóg beter.

Ik gebruik de lengte van 255 karakters omdat dit in een CHAR(255) past van een MySQL-kolom.

Het kan nog veiliger door (a) daar een veel langere string van te maken en die (b) op te slaan in een andere tabel, die (c) liefst op een compleet andere server is opgeslagen. Met ander woorden: dan sla je het wachtwoord en de salt bij dat wachtwoord op in een compleet andere omgeving.
Gewijzigd op 01/11/2014 21:39:31 door Ward van der Put
 
Wouter Van Marrum

Wouter Van Marrum

01/11/2014 21:51:19
Quote Anchor link
Omdat ik normaal gezien salt nooit in me db opsla dus vandaar me vraag of het niet overkill is.
Ik genereer vaak een system wide salt, ( dus statisch ).

Ook maakt het toch niet uit of je salt in de database of in een config bestand opslaat ?
Dacht ooit te hebben gelezen dat de salt in een config bestand mag staan en een eventuele pepper in de db.

Maar niet iedereen heeft toegang tot een extra mysql server waar je wachtwoord met salt opslaat.
Hoe zou je dit aanpakken dan ? ( als je perse een andere omgeving wilt hebben daarvoor ? )
Via een sqllite bestand ?
 
Ward van der Put
Moderator

Ward van der Put

01/11/2014 22:04:03
Quote Anchor link
Klopt, maar als je het écht veilig wilt oplossen, dan gebruik je een universele "system salt" plus een unieke "password salt" per gebruiker.

De hash daarvan is vereenvoudigd in pseudo-code:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$stored_password_hash = some_hash_function($password . $system_salt . $password_salt);


In plaats van één systeem-salt voor alle gebruikers gebruik je dus een unieke salt voor elke individuele gebruiker. Die verschuiving van niveau, van systeem naar gebruiker, geeft een veel sterkere beveiliging.
 
Wouter Van Marrum

Wouter Van Marrum

01/11/2014 22:28:10
Quote Anchor link
Wow nooit over nagedacht.
Dus als ik het extreem makkelijk zou doen dan wordt het zoiets :
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php

$random_salt
= $iv = mcrypt_create_iv(255, MCRYPT_DEV_URANDOM);
$save_password = password_hash($password, PASSWORD_BCRYPT, ["cost"=> 10, "salt"=>$system_salt.$random_salt]);

// Nu heeft system_salt een lengte van 255 en random_salt ook.

?>


Of zou jij bijvoorbeeld een UUID gebruiken als random_salt ?
 
Willem vp

Willem vp

01/11/2014 22:35:35
Quote Anchor link
> Langer is beter.
> Nog langer is nóg beter.

Niet mee eens. Het heeft geen nut om een salt te gebruiken die langer is dan de hash die je genereert. Dus als je een hash hebt van 256 bits, is elke salt van meer dan 32 bytes (256 bits) niet meer dan verspilde opslagruimte.
 
Dos Moonen

Dos Moonen

01/11/2014 23:32:44
Quote Anchor link
Doe niet zo moeilijk... Laat password_hash() zelf de salt genereren. Dat is je unieke salt per gebruiker.
Voor de salt voor je hele systeem is er de volgende constructie: bcrypt(hmac(password))

The first rule of crypto club: don't roll your own!

Default algoritme voor password_hash() is Bcrypt (op tijd van schrijven) wat betekend dat van de password parameter maximaal 22 tekens gebruikt worden.
Ook betekend het dat van de salt maar 22 tekens (en van de laatste maar 4 van de 8 bits) gebruikt worden. En dan ook alleen maar tekens uit het volgende alfabet:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
0-9A-Za-z./

Wat jullie hier boven doen geeft dus een vals gevoel van veiligheid.

De salt wordt in de hash opgeslagen, daar is in de database dus geen appart veld voor. Ookal is een bcrypt hash 60 tekens, maak het veld een varchar(255) en laat password_hash() PASSWORD_DEFAULT gebruiken zodat als je ooit eens naar PHP 8 upgrade (er vanuit gaand dat PHP 8 een andere default heeft) je automatisch een sterker algoritme gebruikt voor het hashen.

Anyway, je komt dan uit op iets als dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

$options
= [];
$null_byte = chr(0);

// get bytes for the maximum entropy
$hmac = hash_hmac('sha512', $password, $system_salt, true);

if (PASSWORD_DEFAULT === PASSWORD_BCRYPT) {
  // strip null bytes since bcrypt assumes zero terminated strings
  //$hmac .= hash_mac('sha512', strrev($password), $system_salt, true); // for the paranoid that fear more then 56 null bytes

  $hmac = strreplace($null_byte, '', $hmac);

  $options['cost'] = 42; // DON'T PANIC! http://nl1.php.net/manual/en/function.password-hash.php#example-923
  unset($options['salt']); // password_hash() can do this just fine
}

$hash = password_hash($hmac, PASSWORD_DEFAULT, $options);

?>
Gewijzigd op 02/11/2014 13:31:02 door Dos Moonen
 
Ward van der Put
Moderator

Ward van der Put

01/11/2014 23:55:59
Quote Anchor link
Dos Moonen op 01/11/2014 23:32:44:
The first rule of crypto club: don't roll your own!

Helemaal mee eens!

Alleen... ik heb het nergens over het opslaan van de hash van een wachtwoord gehad, hé? ;-)

Het gaat hier niet om een wachtwoord, niet om een hash, niet om het algoritme, maar primair om de salt.

Ik begrijp jullie overwegingen, en ben ook heel dankbaar voor de input, maar jullie zijn allemaal één stap verder dan de eigenlijke vraag: hoe genereer je een veilig salt (mijn vraag) en hoe sla je die op (Wouters vraag).
 
Wouter Van Marrum

Wouter Van Marrum

02/11/2014 00:02:07
Quote Anchor link
Haa dos,

Was al benieuwd wanneer jij zou reageren. ( gezien het feit dat je altijd op deze topics reageert haha )
Prima dat dat password_hash zelf een salt aanmaakt natuurlijk, Maar volgens mij maak het weinig uit als je een eigen salt gebruikt toch ?
Ze geven niet voor niks de optie om deze zelf te kunnen aanpassen lijkt me.

Je stopt geen rotzooi in een functie die voor de beveiliging is, Dus waarom zou je dan geen eigen salt kunnen gebruiken icm password_hash ?
 
Dos Moonen

Dos Moonen

02/11/2014 13:33:31
Quote Anchor link
Ward van der Put op 01/11/2014 23:55:59:
Dos Moonen op 01/11/2014 23:32:44:
The first rule of crypto club: don't roll your own!

Helemaal mee eens!

Alleen... ik heb het nergens over het opslaan van de hash van een wachtwoord gehad, hé? ;-)

Het gaat hier niet om een wachtwoord, niet om een hash, niet om het algoritme, maar primair om de salt.

Mijn reactie was niet voor jou bedoeld. Jouw topic is een stuk algemener, binnen dit topic gaat het over het genereren van een salt voor het gebruik binnen password_hash(), waarop mijn antwoord blijft "doe niet zo moeilijk en laat password_hash() dit voor je doen".

Al krijg ik wel het idee dat je te veel waarde hecht aan salts. Passwords zijn secrets, salts niet. Salts zijn een implementation detail. De reden dat we de salts niet op profielen zetten is omdat er geen reden voor is.

Wouter Van Marrum op 02/11/2014 00:02:07:

Ze geven niet voor niks de optie om deze zelf te kunnen aanpassen lijkt me.

Klopt, ze geven die optie zodat je er gebruik van kunt maken als je er een reden voor hebt. "Ik doe het omdat het kan" is in dit geval geen goede reden. Als je het over skydiven zou hebben zou het wat mij betreft een prima reden zijn. Maar wanneer je het over security hebt? NOPE!

Wouter Van Marrum op 02/11/2014 00:02:07:

Je stopt geen rotzooi in een functie die voor de beveiliging is, Dus waarom zou je dan geen eigen salt kunnen gebruiken icm password_hash ?

Omdat je moet weten wat je doet. Wat betekend dat het makkelijker is om het aan password_hash() over te laten. Zelf dingen doen terwijl het niet nodig is doe je wanneer je iets wilt leren, en dat betekend dat je die code niet schrijft met het doel om het in productie te draaien.

Ik krijg nou niet echt het idee dat jij weet wat je moet doen. Dus ik zou die vraag kunnen beantwoorden met "omdat ik bang ben dat JIJ er rotzooi in stopt". En dat zou jammer zijn.

Mocht je willen weten welke random source PHP gebruikt voor het genereren van de salt:
http://lxr.php.net/xref/PHP_5_6/ext/standard/password.c#127

PS. ik ben schuldig aan het gebruiken van $system_salt op de plaats van de key bij hash_hmac(). Keys zijn in tegenstelling to salts wel geheimen. Zolang het geen public keys zijn dan...
 
Wouter Van Marrum

Wouter Van Marrum

02/11/2014 17:12:32
Quote Anchor link
Oke dos, snap deels wat je bedoelt.
Maar het gaat mij niet zozeer om een salt die ik in password_hash gebruik.
Dat was meer een voorbeeld om te geven met de vraag of het zo gedaan kon worden.

Mijn salt wil ik voor encryption en decrytion gebruiken indien dit nodig zou zijn.
Maar om terug te komen op mijn vraag, Hoe zou jij een random maken die wordt aangemaakt bij een installatie van een script ?
Dus hoelang, characters heb je al laten zien en of je het alleen in php of ook in js zou doen.
 
Willem vp

Willem vp

02/11/2014 18:14:25
Quote Anchor link
> Mijn salt wil ik voor encryption en decrytion gebruiken indien dit nodig zou zijn.

Tsja, wat zal ik hier nu eens op zeggen...

Is het voldoende als ik zeg dat een salt per definitie alleen gebruikt wordt bij hashing? ;-)
 
Ward van der Put
Moderator

Ward van der Put

02/11/2014 18:36:52
Quote Anchor link
>> Maar om terug te komen op mijn vraag, Hoe zou jij een random maken die wordt aangemaakt bij een installatie van een script ?

Wilt je elk geïnstalleerd exemplaar voorzien van een unieke ID, als een soort fingerprint?

Of wil je per geïnstalleerd exemplaar een unieke systeem-salt gebruiken?
Gewijzigd op 02/11/2014 18:38:03 door Ward van der Put
 
Wouter Van Marrum

Wouter Van Marrum

02/11/2014 18:47:46
Quote Anchor link
@willem, wat je zegt klopt normaal gezien gebruik ik het ook alleen voor hashen.
Maar met encryption en decryption gebruik je ook een unieke key.

Ben van plan om die op een bepaalde manier te genereren per gebruiker ( anders kun je alles decrypten. ) maar wel gekoppeld met de system_salt.

@ward, ik zou per geinstalleerd exemplaar een unieke systeem salt gebruiken.
Dus de gebruiker maakt zelf een systeem salt ( door zelf wat te verzinnen ) of gebruik te maken van me js functie die random iets genereert.

Maar nu je het over fingerprint hebt breng je me wel op een idee. ( morgen op werk eens over nadenken )
 
Stefan Fransen

Stefan Fransen

04/11/2014 08:29:41
Quote Anchor link
What hash algorithm should I use?

DO use:
The PHP source code at the bottom of this page.
OpenWall's Portable PHP password hashing framework
Any modern well-tested cryptographic hash algorithm, such as SHA256, SHA512, RipeMD, WHIRLPOOL, SHA3, etc.
Well-designed key stretching algorithms such as PBKDF2, bcrypt, and scrypt.
Secure versions of crypt ($2y$, $5$, $6$)

DO NOT use:
Outdated hash functions like MD5 or SHA1.
Insecure versions of crypt ($1$, $2$, $2x$, $3$).
Any algorithm that you designed yourself. Only use technology that is in the public domain and has been well-tested by experienced cryptographers.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php
/*
 * Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).
 * Copyright (c) 2013, Taylor Hornby
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

// These constants may be changed without breaking existing hashes.

define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTE_SIZE", 24);
define("PBKDF2_HASH_BYTE_SIZE", 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_BYTE_SIZE, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" .
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTE_SIZE,
            true
        ));
}

function
validate_password($password, $correct_hash)
{

    $params = explode(":", $correct_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))
        trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
    if($count <= 0 || $key_length <= 0)
        trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);

    if (function_exists("hash_pbkdf2")) {
        // The output length is in NIBBLES (4-bits) if $raw_output is false!
        if (!$raw_output) {
            $key_length = $key_length * 2;
        }

        return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
    }


    $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));
}

?>
Gewijzigd op 04/11/2014 08:31:41 door Stefan Fransen
 



Overzicht Reageren

 
 

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.