Question

I'd like some help coming up with a safe and future-forward way to sanitize hash strings which were originally generated by password_hash().

password_hash() will be implemented on my system with the default algorithm PASSWORD_DEFAULT integer, which would be bcrypt() encryption, however it can change in the future versions of PHP.

None of the manual pages I've read explicitly state what characters may be generated by this algorithm.

Can anyone suggest a minimum amount of sanitizing that would work? Maybe...

filter_var( $hashedPassword, FILTER_SANITIZE_STRING ); 

or

preg_replace( '/^[a-zA-Z0-9-\$\=]*$/', '', $hashedPassword );

If you have something specific for bcrypt, but not necessarily whatever PHP changes to in the future and I have to update my regex string in the future, well that's the breaks, let me know and I'll consider it.

Thanks for any help.

P.S. If you wonder why bother sanitize them, well because it's being passed around a bit across two systems because of some password migration we're doing from one system to another and it just feels dirty not sanitizing my function's input when coming from another system :)

Was it helpful?

Solution

Well, password_hash() is basically just a nicer implementation of the crypt() function, using the Blowfish algorithm by default:

crypt('somepassword', '$2y$10$randomlygeneratedsalt$');

The crypt() function returns a string that looks like this:

$2y$10$randomlygeneratedsalte2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi

It uses $ delimiters to separate the segments:

  1. Algorithm
  2. Cost
  3. Salt/hash combination

From the documentation (emphasis is mine):

[...] Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". [...] The two digit cost parameter [...] must be in range 04-31 [...]

The hash itself is a base64 encoded string using . and / as the two last characters.

In other words, a hash generated by password_hash() contains:

[a-zA-Z0-9$/.]

And it is 60 characters long.

I do not know why you would want to sanitize it (a hash should never be modified, so there should not be anything to sanitize), but something like this should work:

$sanitized = filter_var($hash, FILTER_CALLBACK, ['options' => function($hash) {
    return preg_replace('/[^a-zA-Z0-9$\/.]/', '', $hash);
}]);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top