bcrypt icon indicating copy to clipboard operation
bcrypt copied to clipboard

Invalid salt when setting salt manually in versions 4.0+

Open jose-lpa opened this issue 9 months ago • 1 comments

Sorry if this is not the correct channel to ask this question, but I cannot find any answers to it.

This code works fine in any version less than 4.0.0:

import bcrypt

# A predefined salt in the correct format (with a valid 22-character base64 encoded salt)
# Example format: "$2b$12$abcdefghijklmnopqrstuvwxz"
predefined_salt = b"$2b$12$abcdefghijklmnopqrstuvwxz"  # 22 characters after the cost

# Hash the password using the predefined salt
password = b"my_secure_password"
hashed = bcrypt.hashpw(password, predefined_salt)

print(f"Hashed password: {hashed}")

Will invariably print this, because the salt has been set manually:

Hashed password: b'$2b$12$abcdefghijklmnopqrstuuWPjIcbaogT1FbIphDv1Lk3mqxnJWwO2'

However, it doesn't seem to work anymore when I upgrade from versions 3.x to 4.x. The line

hashed = bcrypt.hashpw(password, predefined_salt)

returns a ValueError: invalid salt exception.

I wonder if this is totally intentional, and therefore is not possible to set a static salt anymore?

My problem, and use case, is that I have to migrate a production codebase which DB has all the user passwords stored with a specific predefined salt that is stored as a secret in the infra. So I can definitely not use the, otherwise absolutely sensible, bcrypt.gensalt() function.

Thanks.

jose-lpa avatar Mar 12 '25 15:03 jose-lpa

The first 22 digits of the salt need to be, by themselves, valid base64 which decode to 16 bytes. Other than that, passing your own salts is allowable: https://github.com/pyca/bcrypt/blob/main/src/_bcrypt/src/lib.rs#L83-L122

alex avatar Apr 27 '25 21:04 alex