Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Do bcrypt hashing in a background thread #2773

Merged
merged 1 commit into from
Jan 10, 2018
Merged
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
24 changes: 16 additions & 8 deletions synapse/handlers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from twisted.internet import defer
from twisted.internet import defer, threads

from ._base import BaseHandler
from synapse.api.constants import LoginType
Expand All @@ -22,6 +22,7 @@
from synapse.types import UserID
from synapse.util.async import run_on_reactor
from synapse.util.caches.expiringcache import ExpiringCache
from synapse.util.logcontext import make_deferred_yieldable

from twisted.web.client import PartialDownloadError

Expand Down Expand Up @@ -626,7 +627,7 @@ def _check_local_password(self, user_id, password):
if not lookupres:
defer.returnValue(None)
(user_id, password_hash) = lookupres
result = self.validate_hash(password, password_hash)
result = yield self.validate_hash(password, password_hash)
if not result:
logger.warn("Failed password login for user %s", user_id)
defer.returnValue(None)
Expand Down Expand Up @@ -754,10 +755,13 @@ def hash(self, password):
password (str): Password to hash.

Returns:
Hashed password (str).
Deferred(str): Hashed password.
"""
return bcrypt.hashpw(password.encode('utf8') + self.hs.config.password_pepper,
bcrypt.gensalt(self.bcrypt_rounds))
def _do_hash():
return bcrypt.hashpw(password.encode('utf8') + self.hs.config.password_pepper,
bcrypt.gensalt(self.bcrypt_rounds))

return make_deferred_yieldable(threads.deferToThread(_do_hash))

def validate_hash(self, password, stored_hash):
"""Validates that self.hash(password) == stored_hash.
Expand All @@ -767,13 +771,17 @@ def validate_hash(self, password, stored_hash):
stored_hash (str): Expected hash value.

Returns:
Whether self.hash(password) == stored_hash (bool).
Deferred(bool): Whether self.hash(password) == stored_hash.
"""
if stored_hash:

def _do_validate_hash():
return bcrypt.hashpw(password.encode('utf8') + self.hs.config.password_pepper,
stored_hash.encode('utf8')) == stored_hash

if stored_hash:
return make_deferred_yieldable(threads.deferToThread(_do_validate_hash))
else:
return False
return defer.succeed(False)


class MacaroonGeneartor(object):
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def register(
yield run_on_reactor()
password_hash = None
if password:
password_hash = self.auth_handler().hash(password)
password_hash = yield self.auth_handler().hash(password)

if localpart:
yield self.check_username(localpart, guest_access_token=guest_access_token)
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/set_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, hs):

@defer.inlineCallbacks
def set_password(self, user_id, newpassword, requester=None):
password_hash = self._auth_handler.hash(newpassword)
password_hash = yield self._auth_handler.hash(newpassword)

except_device_id = requester.device_id if requester else None
except_access_token_id = requester.access_token_id if requester else None
Expand Down