Understanding bcrypt salt as used by PHP password_hash
<p>I have some trouble to understand how bcrypt uses the salt. I know what the salt is good for but I do not understand how the salt value is used exactly.</p>

<p><strong>Problem 1:</strong> What is the correct salt length?</p>

<p>All sources I found say, that the salt has a length of 22 and that it is stored together with the algorithm, the costs and the actual hash value in the result string.</p>

<p><a href="https://i.stack.imgur.com/m8opZ.png" rel="noreferrer"><img src="https://i.stack.imgur.com/m8opZ.png" alt="enter image description here"></a></p>

<p>However, all implementations I found, use a salt with length 32. For example the <code>FOSUserBundle</code> used by <code>Symfony</code> used the following code to creat the salt:</p>

<pre><code>$this-&gt;salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36)
</code></pre>

<p>Since a <code>sha1</code> hash is 32 chars long, the generated salt also has a length of 32. <strong>Is this just a lazy implementation, skipping the code to trim the string to a length of 22 because this is done by <code>bcrypt</code> it self? Or are 32 chars necessary for some reason?</strong></p>

<p><strong>Problem 2:</strong> Is a salt length of 22 really correct?</p>

<p>In the following example it seems, that only the first 21 chars of the salt are saved in the result string. Passing these 21 chars as salt to <code>password_hash</code> will result in an error, but padding a 0 will work:</p>

<pre><code>$s = 'password';
$salt        = 'salt5678901234567890123456789012';
$salt_prefix = 'salt567890123456789010'; // first 21 chars of salt + 0

$h1 = password_hash($s, PASSWORD_BCRYPT, array('salt' =&gt; $salt));
$h2 = password_hash($s, PASSWORD_BCRYPT, array('salt' =&gt; $salt_prefix));

echo $h1 . PHP_EOL;
echo $h2 . PHP_EOL;

//Result
$2y$10$salt56789012345678901uTWNlUnhu5K/xBrtKYTo7oDy8zMr/csu
$2y$10$salt56789012345678901uTWNlUnhu5K/xBrtKYTo7oDy8zMr/csu
</code></pre>

<p>So, one needs to pass a salt with at least 22 chars to the algorithm but the 22nd chars seems to be useless. Is that correct? What is the sense of the 22nd char if it is not used at all?  </p>

<p><strong>Problem 3:</strong> Why not specify the salt manually?</p>

<p>In the PHP function <code>password_hash</code> using a manual hash is deprecated. Instead one is encouraged to let <code>password_hash</code> automatically, since would be safer.</p>

<p>I understand that using a "weak" salt or the same salt for all passwords can lead to risks due to rainbow tables. But why is it safer to use the auto-generated salt in general?</p>

<p>Why is it safer to use the auto-generated salt instead of manual salt, that is generated like this:</p>

<pre><code>$this-&gt;salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36)
</code></pre>

<p><strong>Problem 4:</strong> Is there any replacement for <code>password_hash</code> that still allows the usage of a custom salt?</p>

<p>Due to the implementation of project I am working on, I need to control the salt, that is used to generate a password hash. This can be changed in the future, but right know it is necessary to set the salt manually. Since this feature is deprecated in <code>password_hash</code>, I need some alternative to generate the hash. How to do this?</p>

<p><strong>EDIT:</strong></p>

<p>Just a short explanation why I need to control the salt: The password is not only used to login into the web app directly, but also to connect to the app via a REST API. The client requests the salt from the server and uses it (algorithm and costs are known) to hash the password, the user entered on the client side.</p>

<p>The hashed password then send back to the server for authentication. The purpose is to not send the password in plain text. To be able to generate the same hash on the client as on the server, the client needs to know which salt the server used. </p>

<p>I know that a hashed password does not add any real security, since the communication is already uses HTTPS only. However this the way the clients currently operate: Authentication is granted if the client send back the correct password hash.</p>

<p>I cannot change the server side without breaking thousands of existing clients. The clients can be updated sometime in the future, but this will be a long process. </p>

<p>Since this is done, I need to follow the old process, which means I need to be able to tell the clients the salt.</p>

<p>However I do <strong>not</strong> need to generate the salt myself. I am totally fine if PHP knows the most secure way how to do this. But I do need to get/extract the salt someway, to send it to the clients.</p>

<p><strong>If I understood everything correctly, I could just let <code>password_hash</code> do the work and then extract the chars 7-29 from result string. Is this correct?</strong></p>