Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/19078.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a bug introduced in 1.140.0 where an internal server error could be raised when hashing user passwords that are too long.
12 changes: 11 additions & 1 deletion synapse/_scripts/hash_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,18 @@ def main() -> None:

pw = unicodedata.normalize("NFKC", password)

bytes_to_hash = pw.encode("utf8") + password_pepper.encode("utf8")
if len(bytes_to_hash) > 72:
# bcrypt only looks at the first 72 bytes
print(
f"Password is too long ({len(bytes_to_hash)} bytes); truncating to 72 bytes for bcrypt. "
"This is expected behaviour and will not affect a user's ability to log in. 72 bytes is "
"sufficient entropy for a password."
)
bytes_to_hash = bytes_to_hash[:72]

hashed = bcrypt.hashpw(
pw.encode("utf8") + password_pepper.encode("utf8"),
bytes_to_hash,
bcrypt.gensalt(bcrypt_rounds),
).decode("ascii")

Expand Down
15 changes: 14 additions & 1 deletion synapse/handlers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -1683,8 +1683,21 @@ def _do_hash() -> str:
# Normalise the Unicode in the password
pw = unicodedata.normalize("NFKC", password)

bytes_to_hash = pw.encode(
"utf8"
) + self.hs.config.auth.password_pepper.encode("utf8")
if len(bytes_to_hash) > 72:
# bcrypt only looks at the first 72 bytes
logger.debug(
"Password is too long (%d bytes); truncating to 72 bytes for bcrypt. "
"This is expected behaviour and will not affect a user's ability to log in. 72 bytes is "
"sufficient entropy for a password.",
len(bytes_to_hash),
)
bytes_to_hash = bytes_to_hash[:72]

return bcrypt.hashpw(
pw.encode("utf8") + self.hs.config.auth.password_pepper.encode("utf8"),
bytes_to_hash,
bcrypt.gensalt(self.bcrypt_rounds),
).decode("ascii")

Expand Down
Loading