php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #81473 hash_pbkdf2 truncate in hex
Submitted: 2021-09-24 09:04 UTC Modified: 2021-09-25 15:58 UTC
From: php at wfuchs dot de Assigned:
Status: Closed Package: hash related
PHP Version: 8.0.11 OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: php at wfuchs dot de
New email:
PHP Version: OS:

 

 [2021-09-24 09:04 UTC] php at wfuchs dot de
Description:
------------
Tested Versions:
PHP 8.0.11 (cli) (built: Sep 23 2021 21:26:24)
PHP 7.4.24 (cli) (built: Sep 23 2021 21:36:11)
Compiled by Ondřej Surý for Ubuntu 20.04

In the PHP function "hash_pbkdf2" the key is truncated in hex (default). With a length of 64 bytes it should be 128 hexits and not 64 hexits.
If the key is generated binary and converted to hex the length is correct with 128 hexits.

Test script:
---------------
<?php
$algo       = "sha256";
$password   = "S€cur@Päßw#rd";
$salt       = random_bytes(16);
$iterations = 10000;

$binhash = hash_pbkdf2($algo, $password, $salt, $iterations, 64, TRUE);
echo ("Converted to HEX:" . PHP_EOL);
var_dump(bin2hex($binhash));

$hexhash = hash_pbkdf2($algo, $password, $salt, $iterations, 64);
echo ("HEX generated:" . PHP_EOL);
var_dump($hexhash);
?>

Expected result:
----------------
Converted to HEX:
string(128) "b94864e32adfd58bd9324ed058ed3c40e0134f98af8abde2535576bab28ddd3e3c205381c33a705f63d75db4c340ccec288985f9ff1b917c53b419ee166083d0"
HEX generated:
string(128) "b94864e32adfd58bd9324ed058ed3c40e0134f98af8abde2535576bab28ddd3e3c205381c33a705f63d75db4c340ccec288985f9ff1b917c53b419ee166083d0"

Actual result:
--------------
Converted to HEX:
string(128) "b94864e32adfd58bd9324ed058ed3c40e0134f98af8abde2535576bab28ddd3e3c205381c33a705f63d75db4c340ccec288985f9ff1b917c53b419ee166083d0"
HEX generated:
string(64) "b94864e32adfd58bd9324ed058ed3c40e0134f98af8abde2535576bab28ddd3e"

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-09-24 10:15 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2021-09-24 10:15 UTC] cmb@php.net
This behaves as advertized[1]:

| length
|
| The length of the output string. If binary is true this
| corresponds to the byte-length of the derived key, if binary is
| false this corresponds to twice the byte-length of the derived key
| (as every byte of the key is returned as two hexits).

[1] <https://www.php.net/hash_pbkdf2>
 [2021-09-24 19:14 UTC] php at wfuchs dot de
The behavior the function describes 

"if binary is false this corresponds to twice the byte-length of the derived key (as every byte of the key is returned as two hexits)"

The length in hex should be 128 and not 64 right?
 [2021-09-24 19:54 UTC] salathe@php.net
> The length in hex should be 128 and not 64 right?

No. The $length parameter dictates the length of the returned string. If you pass 64, the length of the returned string will be 64.
 [2021-09-25 12:25 UTC] php at wfuchs dot de
I am addressing the part you posted:
"if binary is false this corresponds to twice the byte-length".
In my opinion this is a security related bug that weakens the cryptography and makes the implementation incompatible to other languages:
256 different possibilities can be represented in one byte. That is 256^64 in binary form. Hexits are only the numbers 0-9 and the letters A-F which makes a maximum of 16 possible hexits. Therefore there are only 16^64 which is much less.
If you use 2 hexits per byte you get 16^2 which is 256 again.
 [2021-09-25 15:43 UTC] requinix@php.net
> In my opinion this is a security related bug
It is always a security bug to call hashing functions without understanding how they should be used.

hash_pbkdf2 is a key derivation function. Its purpose is to generate a key that will presumably be fed into something else of a cryptographic nature. That "something else" might want binary bytes or it might want a hexit string. $length and $binary control hash_pbkdf2's output so a developer doesn't have to do further work with substr/bin2hex/hex2bin to be able to use the returned value as needed.

If you want a hexit string of length 128 (ie. 512 bits or two SHA256 hash blocks) then pass $binary=false and $length=128. Which is what the documentation says.
 [2021-09-25 15:58 UTC] requinix@php.net
-Status: Not a bug +Status: Re-Opened -Type: Bug +Type: Documentation Problem -Assigned To: cmb +Assigned To:
 [2021-09-25 15:58 UTC] requinix@php.net
How about we add a second example to the page showing how $binary and $length affect the return value?
 [2021-09-27 12:34 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/doc-en/commit/8ad9c12d9bf30c0a0c06f150643c0669d02c3125
Log: Fix #81473: hash_pbkdf2 truncate in hex
 [2021-09-27 12:34 UTC] git@php.net
-Status: Re-Opened +Status: Closed
 [2021-09-27 15:24 UTC] git@php.net
Automatic comment on behalf of mumumu
Revision: https://github.com/php/doc-ja/commit/3c4fcc27b343750f3de85ba14026280c56fedecb
Log: Fix #81473: hash_pbkdf2 truncate in hex
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Dec 03 08:01:28 2024 UTC