However, it doesn’t work as expected as I’m unable to generate a master passwor hash that match the one on vaultwarden DB.
First of all I have few questions regarding how vaultwarden do create the master_password_hash saved on DB:
Because vaultwarden store the salt as a blob on SQLite DB I do extract it assuming it’s a hexadecimal string using: sqlite> select hex(salt) from users where email@example.com';
Am I correct?
Same question for the master_password_hash
It looks like the official bitwarden client use a b64 encoded master_key string to generate the master_password_hash: https://github.com/bitwarden/clients/blob/master/libs/common/src/platform/services/crypto.service.ts#L256
Did I correctly understood the return of this hashMasterKey function?
Same question for the master_password_hash function.
Here is my current workflow, did I missed something or am I on the right path?
Create a master_key derivated from master_password and email using:
Trying to create a master_password_hash salted as on DB using DB information using:
Function: PBKDF2-HMAC-SHA256 Payload: master password hash Salt: random bytes → using string stored in DB transform as bytes array. iteration: 100 000 key length: 32 hash protocol and function: hmac-sha256
Now my issue is, when I do compare my locally computed master_password_hash it doesn’t match the one from DB.
I tried to use a b64 encoded master_password_hash as input instead of the string master_password_hash, it doesn’t match neither.
Yes, I’ve seen that, it’s not specifically vaultwarden that use the byte representation, python’s PBKDF2 from cryptodome is also using that and I’m also used it as it to compute it.
However, I think there is something odd at the client side of bitwarden as if you simply code your workflow steps using what’s explain there, then it doesn’t work.
Their own source code seems to explain that they b64 encode the hash and return it, which then in turn vaultwarden do byte translate and iterate over 600k or 100k times + salt depending on your setting and vaultwarden server version. Mine is using 100k so far as stated on DB for few accounts that were created before the upgrade to 600k.
I’ve carefully read @nozza87 thread you’re mentioning too but unfortunately he didn’t responded yet.
I would really appreciate anyone looking at the client sources that have linked on my first link as I’m a bit lost on bitwarden monorepo and extensive TypeScript usage.
From my investigation it seems that:
1°/- They always return b64 encoded hashes from the derivation function, would it be for master key creation AND password hash.
2°/- Unfortunately when I try to do it that way too and then calculate the expected master_password_hash using DB salt and bytes representation I can’t get the same master_password_hash that the one stored on vaultwarden.
3°/- I’ll probably have to compile my desktop client from upstream sources with debugging modification in order to find out what’s the client is really sending to the server as the payload.
Thanks a lot at least for your kind answer and care about this topic that I really can’t get any satisfying answers anywhere :-/ Even Bitwarden communication channels doesn’t work, I really feel like if I missed something somewhere that everybody else out there already clicked xD
It works perfectly for me. At least when using PBKDF2. It will fail when using Argon2, since that is not (yet) implemented into that page. Also, check what the response is of the /identity/accounts/prelogin call, this will contain the values needed to generate the correct key, like which hashing algo and how many iterations.