hash_pbkdf2

(PHP 5 >= 5.5.0, PHP 7)

hash_pbkdf2Формирования ключа PBKDF2 для заданных входных данных

Описание

string hash_pbkdf2 ( string $algo , string $password , string $salt , int $iterations [, int $length = 0 [, bool $raw_output = false ]] )

Список параметров

algo

Имя выбранного хеширующего алгоритма (т.е. md5, sha256, haval160,4, и т.д.) Список поддерживаемых алгоритмов смотри в описании функции hash_algos().

password

Пароль, используемый для формирования.

salt

Соль, используемая при формировании ключа. Значение необходимо генерировать случайным образом.

iterations

Количество итераций для формирования ключа.

length

Длина генерируемой строки. Если параметр raw_output задан как TRUE, то этот параметр равен количеству байт в генерируемом ключе. Если raw_output установлен как FALSE, то то длина ключа в байтах будет в два раза меньше, так как каждый байт ключа будет возвращен в виде двух символов шестнадцетиричной системы (0-F).

Если задано как 0, то используется весь вывод заданного алгоритма.

raw_output

Если кстановлено как TRUE, то вывод будет представлять из себя сырые бинарные данные, а если как FALSE, то вывод будет представлен в виде строки шестнадцетиричных цифр в нижнем регистре.

Возвращаемые значения

Возвращаемая строка содержит сформированный ключ в виде строки шестнадцетиричных чисел в нижнем регистре. Но если параметр raw_output установлен как TRUE, то будут возвращены сырые бинарные данные.

Ошибки

Ошибка уровня E_WARNING будет вызвана если: заданный алгоритм некорректен, параметр iterations меньше или равен 0, параметр length меньше чем 0 или если salt очень длинный (больше чем INT_MAX - 4).

Список изменений

Версия Описание
7.2.0 Запрещено использование некриптографических функций (adler32, crc32, crc32b, fnv132, fnv1a32, fnv164, fnv1a64, joaat).

Примеры

Пример #1 Пример простого использования hash_pbkdf2()

<?php
$password 
"password";
$iterations 1000;

// Создаем случайный инициализирующий вектор 
// с помощью openssl_random_pseudo_bytes() или другого источника случайных данных
$salt openssl_random_pseudo_bytes(16);

$hash hash_pbkdf2("sha256"$password$salt$iterations20);
echo 
$hash;
?>

Результатом выполнения данного примера будет что-то подобное:

120fb6cffcf8b32c43e7

Примечания

Предостережение

Метод PBKDF2 может быть использован для хеширования паролей в целях их хранения. Однако стоит помнить, что для этих целей гораздо лучше использовать password_hash() или crypt() с CRYPT_BLOWFISH.

Смотрите также

  • crypt() - Необратимое хэширование строки
  • password_hash() - Создает хеш пароля
  • hash() - Генерирует хеш-код (дайджест сообщения)
  • hash_algos() - Возвращает список зарегистрированных алгоритмов хеширования
  • hash_init() - Инициализация инкрементального контекста хеширования
  • hash_hmac() - Генерация хеш-кода на основе ключа, используя метод HMAC
  • hash_hmac_file() - Генерация хеш-кода на основе ключа, используя метод HMAC и содержимое полученного файла
  • openssl_pbkdf2() - Генерация строки PKCS5 v2 PBKDF2

add a note add a note

User Contributed Notes 7 notes

up
12
clarence.pchy(at)gmail.com
1 year ago
Please pay great attention to the **$length** parameter! It is exactly the **return string length**, NOT the length of raw binary hash result.

I had a big problem about this --
I thought that `hash_pbkdf2(...false)` should equals to `bin2hex(hash_pbkdf2(...true))` just like `md5($x)` equals `bin2hex(md5($x, true))`. However I was wrong:

hash_pbkdf2('sha256', '123456', 'abc', 10000, 50, false); // returns string(50) "584bc5b41005169f1fa15177edb78d75f9846afc466a4bae05"
hash_pbkdf2('sha256', '123456', 'abc', 10000, 50, true); // returns string(50) "XKŴ��Qw�u��j�FjK���BFW�YpG    �mp.g2�`;N�"
bin2hex(hash_pbkdf2('sha256', '123456', 'abc', 10000, 50, true)); // returns string(100) "584bc5b41005169f1fa15177edb78d75f9846afc466a4bae05119c82424657c81b5970471f098a6d702e6732b7603b194efe"

So I add such a note. Hope it will help someone else like me.
up
8
Anonymous
4 years ago
Sadly this function was added in PHP 5.5 but many webservers just provide PHP 5.3. But there exists a pure PHP implementation (found here: https://defuse.ca/php-pbkdf2.htm).
I took this implementation, put it into a class with comments for PHPDoc and added a switch so that the native PHP function is used if available.

Feel free to use it!
http://pastebin.com/f5PDq735
(Posted on pastebin.com since the text would have been too long)
up
5
Trevor Herselman
2 years ago
This is a light-weight drop-in replacement for PHP's hash_pbkdf2(); written for compatibility with older versions of PHP.
Written, formatted and tested by myself, but using code and ideas based on the following:
https://defuse.ca/php-pbkdf2.htm
https://github.com/rchouinard/hash_pbkdf2-compat/blob/master/src/hash_pbkdf2.php
https://gist.github.com/rsky/5104756

My main goals:
1) Maximum compatibility with PHP hash_pbkdf2(), ie. a drop-in replacement function
2) Minimum code size/bloat
3) Easy to copy/paste
4) No classes, and not encapsulated in a class! Why write a class when a simple function will do?
5) Eliminate calls to sprintf(). (used by other examples for the error reporting)
6) No other dependencies, ie. extra required functions

<?php
if (!function_exists('hash_pbkdf2'))
{
    function
hash_pbkdf2($algo, $password, $salt, $count, $length = 0, $raw_output = false)
    {
        if (!
in_array(strtolower($algo), hash_algos())) trigger_error(__FUNCTION__ . '(): Unknown hashing algorithm: ' . $algo, E_USER_WARNING);
        if (!
is_numeric($count)) trigger_error(__FUNCTION__ . '(): expects parameter 4 to be long, ' . gettype($count) . ' given', E_USER_WARNING);
        if (!
is_numeric($length)) trigger_error(__FUNCTION__ . '(): expects parameter 5 to be long, ' . gettype($length) . ' given', E_USER_WARNING);
        if (
$count <= 0) trigger_error(__FUNCTION__ . '(): Iterations must be a positive integer: ' . $count, E_USER_WARNING);
        if (
$length < 0) trigger_error(__FUNCTION__ . '(): Length must be greater than or equal to 0: ' . $length, E_USER_WARNING);

       
$output = '';
       
$block_count = $length ? ceil($length / strlen(hash($algo, '', $raw_output))) : 1;
        for (
$i = 1; $i <= $block_count; $i++)
        {
           
$last = $xorsum = hash_hmac($algo, $salt . pack('N', $i), $password, true);
            for (
$j = 1; $j < $count; $j++)
            {
               
$xorsum ^= ($last = hash_hmac($algo, $last, $password, true));
            }
           
$output .= $xorsum;
        }

        if (!
$raw_output) $output = bin2hex($output);
        return
$length ? substr($output, 0, $length) : $output;
    }
}
up
5
does dot not at matter dot org
4 years ago
this snippet was posted over a year ago on a dutch PHP community: (reference/source: http://www.phphulp.nl/php/script/beveiliging/pbkdf2-een-veilige-manier-om-wachtwoorden-op-te-slaan/1956/pbkdf2php/1757/)

<?php

/**
* @author Chris Horeweg
* @package Security_Tools
*/

function pbkdf2($password, $salt, $algorithm = 'sha512', $count = 20000, $key_length = 128, $raw_output = false)
{
    if(!
in_array($algorithm, hash_algos(), true)) {
        exit(
'pbkdf2: Hash algoritme is niet geinstalleerd op het systeem.');
    }
   
    if(
$count <= 0 || $key_length <= 0) {
       
$count = 20000;
       
$key_length = 128;
    }

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

   
$output = "";
    for(
$i = 1; $i <= $block_count; $i++) {
       
$last = $salt . pack("N", $i);
       
$last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        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
base64_encode(substr($output, 0, $key_length));
    }
}
up
1
Binod Kumar Luitel
4 years ago
People who wants pure PHP implementation of the function, i.e. who don't have PHP 5.5 installed within their server, can use the following implementation. Nothing has been modified so far as from reference https://defuse.ca/php-pbkdf2.htm but the OOP lovers might like this.
For more information about PBKDF2 see: http://en.wikipedia.org/wiki/PBKDF2

<?php
/**
* 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.
*/
if (!function_exists("hash_pbkdf2")) {
    function
hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) {

        class
pbkdf2 {
            public
$algorithm;
            public
$password;
            public
$salt;
            public
$count;
            public
$key_length;
            public
$raw_output;

            private
$hash_length;
            private
$output         = "";

            public function
__construct($data = null)
            {
                if (
$data != null) {
                   
$this->init($data);
                }
            }

            public function
init($data)
            {
               
$this->algorithm  = $data["algorithm"];
               
$this->password   = $data["password"];
               
$this->salt       = $data["salt"];
               
$this->count      = $data["count"];
               
$this->key_length = $data["key_length"];
               
$this->raw_output = $data["raw_output"];
            }

            public function
hash()
            {
               
$this->algorithm = strtolower($this->algorithm);
                if(!
in_array($this->algorithm, hash_algos(), true))
                    throw new
Exception('PBKDF2 ERROR: Invalid hash algorithm.');

                if(
$this->count <= 0 || $this->key_length <= 0)
                    throw new
Exception('PBKDF2 ERROR: Invalid parameters.');

               
$this->hash_length = strlen(hash($this->algorithm, "", true));
               
$block_count = ceil($this->key_length / $this->hash_length);
                for (
$i = 1; $i <= $block_count; $i++) {
                   
// $i encoded as 4 bytes, big endian.
                   
$last = $this->salt . pack("N", $i);
                   
// first iteration
                   
$last = $xorsum = hash_hmac($this->algorithm, $last, $this->password, true);
                   
// perform the other $this->count - 1 iterations
                   
for ($j = 1; $j < $this->count; $j++) {
                       
$xorsum ^= ($last = hash_hmac($this->algorithm, $last, $this->password, true));
                    }
                   
$this->output .= $xorsum;
                    if(
$this->raw_output)
                        return
substr($this->output, 0, $this->key_length);
                    else
                        return
bin2hex(substr($this->output, 0, $this->key_length));
                }
            }
        }

       
$data = array('algorithm' => $algorithm, 'password' => $password, 'salt' => $salt, 'count' => $count, 'key_length' => $key_length, 'raw_output' => $raw_output);
        try {
           
$pbkdf2 = new pbkdf2($data);
            return
$pbkdf2->hash();
        } catch (
Exception $e) {
            throw
$e;
        }
    }
}
up
1
nimasdj [AT] yahoo [DOT] com
1 year ago
There is a mistake in the class provided by Binod Kumar Luitel (http://php.net/manual/en/function.hash-pbkdf2.php#113488):
this line:
return bin2hex(substr($this->output, 0, $this->key_length));
must be changed to:
return substr(bin2hex($this->output), 0, $this->key_length);
up
-1
Peter
4 years ago
See also https://github.com/rchouinard/hash_pbkdf2-compat for a compatibility function
To Top