Do bcrypt hashing in a background thread

This commit is contained in:
Erik Johnston 2018-01-10 18:01:28 +00:00
parent 624c46eb06
commit f8e1ab5fee
3 changed files with 18 additions and 10 deletions

View file

@ -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
@ -22,6 +22,7 @@ from synapse.module_api import ModuleApi
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
@ -626,7 +627,7 @@ class AuthHandler(BaseHandler):
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)
@ -754,10 +755,13 @@ class AuthHandler(BaseHandler):
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.
@ -767,13 +771,17 @@ class AuthHandler(BaseHandler):
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):

View file

@ -130,7 +130,7 @@ class RegistrationHandler(BaseHandler):
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)

View file

@ -31,7 +31,7 @@ class SetPasswordHandler(BaseHandler):
@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