diff --git a/proton/session/exceptions.py b/proton/session/exceptions.py index 0a6784f..4171b5e 100644 --- a/proton/session/exceptions.py +++ b/proton/session/exceptions.py @@ -33,6 +33,11 @@ class ProtonCryptoError(ProtonError): In general this has to be handled as being fatal, as something is super-wrong.""" +class ProtonCryptoPasswordTooLongError(ProtonCryptoError): + """Exception raised when the password exceeds bcrypt's 72-byte limit. + The user should shorten their password to at most 72 bytes.""" + + class ProtonUnsupportedAuthVersionError(ProtonCryptoError): """When the auth_version returned by the API is lower then what is currently supported. This is usually fixed with a login via the webclient.""" diff --git a/proton/session/srp/util.py b/proton/session/srp/util.py index cedf655..c98d6bc 100644 --- a/proton/session/srp/util.py +++ b/proton/session/srp/util.py @@ -20,7 +20,7 @@ import bcrypt import os -from proton.session.exceptions import ProtonUnsupportedAuthVersionError +from proton.session.exceptions import ProtonUnsupportedAuthVersionError, ProtonCryptoPasswordTooLongError PM_VERSION = 4 @@ -39,7 +39,13 @@ def bcrypt_b64_encode(s): # The joy of bcrypt def hash_password_3(hash_class, password, salt, modulus): salt = (salt + b"proton")[:16] salt = bcrypt_b64_encode(salt)[:22] - hashed = bcrypt.hashpw(password, b"$2y$10$" + salt) + try: + hashed = bcrypt.hashpw(password, b"$2y$10$" + salt) + except ValueError as e: + raise ProtonCryptoPasswordTooLongError( + "Password exceeds bcrypt's 72-byte limit. " + "Please shorten your password to at most 72 bytes." + ) from e return hash_class(hashed + modulus).digest()