# How many possible randomly generated salts could be generated using PHP's password_hash() function?

I have two questions here:

1) How many possible randomly generated salts could be generated using PHP's `password_hash()` function?

2) According to php.net it states that the return value is a contains "the algorithm used, the cost and salt are returned as part of the hash" and I assume the hash itself. So from my understanding in a returned string of `\$2y\$10\$x27FUiXA/hFKjD7NDxyD6e63ac4gmCkTqXRpmy1Rk.MxXAqRd8yO6` the `2y` indicates the algorithm, the `10` indicates the cost, but which characters indicate the salt and which characters indicate the hash?

• Since the length of the password will return a different value you will have to factor that in. According to the PHP docs a password with the length of 8 is 96^8 = 7,21389578984e+15. This number alone for one length is pretty astronomical. So if combination possibilities is a concern you should be able to put that to rest. Apr 1, 2016 at 22:38
• @BradMetcalf Can you point to the place in the docs it mentions this? Your value is very different from the one in the answer below. Apr 1, 2016 at 22:56
• @kojow7 I believe brad is misunderstanding your question. You were specifically asking about the salts which are 128 bit with bcrypt (the current default mode for `password_hash()`) which means that there are 2^128 possible salts. Additionally, this is a hashing function therefore the length shouldn't ever change. I believe brad was thinking you were asking about total number of possible passwords with length `n` or something similar. Apr 2, 2016 at 1:31

1) The salt for `password_hash()` is a 128 bit salt which is the first 22 base64 characters after the cost factor. In your example, the salt would be `x27FUiXA/hFKjD7NDxyD6e`. Because it is 128 bit, you can calculate the number of potential salts as 2^128 which is `3.4028237e+38`. So, in short, a lot.

2) Well this didn't seem like a question so i'll try to answer the "which characters indicate the hash" part. The hash are the remaining 31 characters after the salt. In your case `63ac4gmCkTqXRpmy1Rk.MxXAqRd8yO6`.

(also, your understanding is correct. `2y` is the algorithm, and `10` is the cost.)

It is important to note that `password_hash()` can change its implementation to use a different algorithm if you update PHP to a newer version that changes it.

PASSWORD_DEFAULT - Use the bcrypt algorithm (default as of PHP 5.5.0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP.

If you use `PASSWORD_BCRYPT` it will always use bcrypt.

• To add to this, there's an effort to add Argon2i v1.3 to `password_hash()` as an option in 7.1 and possibly as the default in 7.3/8.0 :) Apr 8, 2016 at 16:00
• @ScottArciszewski Thanks for the additional information, scott. What are your thoughts on using argon in production systems? My understanding is that it has only been "in the wild" for about 3 years and I'm still a little nervous about using it since it's only been out for a relatively short period of time. Apr 8, 2016 at 16:21
• PHP 7.1 will probably come out later this year. Presumably 7.3 will come out at the end of 2018. The primitives that Argon2i is based on are pretty well-studied, so I don't anticipate any significant advances there. The weaknesses, if any, are going to be in the form of "You can optimize your brute force attempts by doing this strategy" e.g. trading 32x memory for a 2x speedup. Apr 9, 2016 at 19:14
• @Scott should I assume, for all intents and purposes, that argon is safe to use, then? Apr 9, 2016 at 21:35
• I would consider Argon2i v1.3 safe to use, but I understand that many do not feel comfortable switching to it just yet. Bcrypt truncates after 72 characters or a single NUL byte. Scrypt has weird corner cases. PBKDF2 is the weakest of the four. Yescrypt / Argon2i are the two I'd trust, personally. `Bcrypt(Base64Encode(SHA384(\$password)))` is a great stop-gap for today. This blog post will be where I keep up-to-date recommendations. Apr 10, 2016 at 1:51