-
Notifications
You must be signed in to change notification settings - Fork 210
Description
While reviewing the hashpw implementation, I noticed behavior that may deserve clarification from a security perspective.
hashpw accepts arbitrary &[u8] as password input, but bcrypt historically processes passwords using C-string semantics and only considers bytes up to the first NUL (0x00) character (and only up to 72 bytes total).
This means the following two inputs may produce identical hashes:
import bcrypt
from os import urandom
def attack(key):
return key + b"\x00" + key
salt = bcrypt.gensalt()
key = urandom(16)
key1 = attack(key)
hash_key = bcrypt.hashpw(key, salt)
hash_key1 = bcrypt.hashpw(key1, salt)
print(hash_key == hash_key1) # True
print(bcrypt.checkpw(key1, hash_key)) # TrueAlthough this behavior may be consistent with the original bcrypt design, the current API:
fn hashpw(password: &[u8], salt: &[u8])suggests that arbitrary binary input is fully supported.
If applications use bcrypt as a generic KDF for binary tokens (API keys, session secrets, etc.), this could lead to credential equivalence where.
Is this behavior intentionally preserved for compatibility?
Should the documentation explicitly warn that NUL bytes terminate effective password