patrickfav / bcrypt

A Java standalone implementation of the bcrypt password hash function. Based on the Blowfish cipher it is the default password hash algorithm for OpenBSD and other systems including some Linux distributions. Includes a CLI Tool.
https://favr.dev/opensource/bcrypt
Apache License 2.0
482 stars 49 forks source link

Strange and Incorrect Hash Output #18

Closed scothampelold closed 5 years ago

scothampelold commented 5 years ago

I am porting an old application of mine from PHP to a personal Java android application. My PHP application creates a BCrypt hash and so I am using your library for this functionality in the app.

Given the salt of $2a$10$bf2a37d5e83e612cdfeebec9e2e71a318e9767cd3e035f4b8ed73eecf2ae8110b3aa3f3688874f7cfae8cb49474369e74cdde7dba7bddf84f0c5f6fc56013715 (I know, it's formatted like a hash, it's old code that I wrote weirdly. But this is 100% the salt), and a password of prof.siko with 10 rounds in the PHP password_hash() function, the returned hash is $2y$10$JDJhJDEwJGJmMmEzN2Q1ZO/Dil6rDX7EQIetkSEj6ZUH.yRJpfezm. I can only assume this function takes trims the extra salt characters not required by the function because of the base64 encoded salt within the returned hash.

I expected the same functionality with your library, yet did not receive it.

I am using the command BCrypt.withDefaults().hash(cost, salt.getBytes(StandardCharsets.UTF_8), password.getBytes(StandardCharsets.UTF_8)) where the salt variable is $2a$10$bf2a37d5e and the password variable is prof.siko. The same as in my PHP tests. This command, however, returns the hash $2a$10$HBHfHBCuHEHkKkCxL0OzXO.9qaZyVOYZO55fiE8ev5Wa2adkFQ0au.

The interesting aspect of this problem to me is the fact that most of the base64 encoded salt portion of the hash produced by your library is shifted down by 2 characters from my PHP result.

HBHfHBCuHEHkKkCxL0OzXO vs JDJhJDEwJGJmMmEzN2Q1ZO

HBHfHBCuHEHkKkCxL0OzXO when shifted becomes JDJhJDEwJGJmMmEzN0QbZQ

PHP Salt decoded: $2a$10$bf2a37d5d Your BCrypt Library salt decoded: $2a$10$bf2a37De

Any help would be greatly appreciated!

scothampelold commented 5 years ago

Additionally after testing, both hashes successfully verify using your library's verify() function.

scothampelold commented 5 years ago

Well, after a bit of work, I solved it. It seems as though you library's BCrypt encoder format's the salt using a Radix-64 encode while PHP's password_hash uses a standard base64 encode. I solved my problem by first encoding my salt with standard base64, then decoding it with your library's Radix-64 decoder. I then used the returned byte array as my salt byte array for your library's hash function. Example code here: Radix64Encoder.Default re = new Radix64Encoder.Default(); byte[] enc = Base64.encode(salt.getBytes(), Base64.DEFAULT); byte[] salt_byte = re.decode(enc);