Skip to content

bcrypt NUL-byte handling may allow equivalent passwords #1164

@oSthing

Description

@oSthing

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))  # True

Although 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions