Bulk User Import of pbkdf2-whirlpool hashed passwords


I am trying to test user import to see if our database can be migrated to auth0 without the need for the customers to change passwords.

Our salts are lowercase hex strings of the length 128
Our hashes are created by php 8.2’s hash_pbkdf2(‘whirlpool’, password, salt, 100000)

Given a random salt


And a password ‘password’

The php delivers following hash:


According to the documentation, the slat and hash have to be base64 encoded with padding = removed.
I then base64 the hash and the salt by chunking the strings into character sequences of length 2, mapping them to int and getting a byte array of the result.

Base64.encode(string.chunked(2).map { it.toInt(16).toByte() }.toByteArray())

I send a post request to the api/v2/users-imports with the hash.value string as follows:


The user is successfully imported but I cannot login with the following error in the logs:

"reason": "Verification failed for the provided custom_password_hash: {'algorithm':'pbkdf2','hash':{'value':'$pbkdf2-whirlpool$i=100000,l=128$D8+K030gpPsy1eVqfCa...'},'salt':{'value':''}}"

I have seen many similar issues but could not solve my problem. Does anybody have suggestion for me what I could try?

1 Like

I have tried different lengths (0,32,64,128,256), leaving the parameters completely out, using string.toByteArray() directly, reversing the chunked string, skipping base64 encoding, to no avail

1 Like

We have found a solution, if anyone is interested. PHP’s hash_pbkdf2 treats salt string not a string containing hex values, it just converts it to bytes - same as what you would get in kotlin by doing string.toByteArray. So in order to correctly convert it to Base64 in our application, we needed to do:


This only applies to salt, the password hash base64 transformation stays as in original post

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.