Merge pull request #2773 from matrix-org/erikj/hash_bg

Do bcrypt hashing in a background thread
This commit is contained in:
Erik Johnston 2018-01-10 18:11:41 +00:00 committed by GitHub
commit 825a07a974
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from twisted.internet import defer from twisted.internet import defer, threads
from ._base import BaseHandler from ._base import BaseHandler
from synapse.api.constants import LoginType from synapse.api.constants import LoginType
@ -25,6 +25,7 @@ from synapse.module_api import ModuleApi
from synapse.types import UserID from synapse.types import UserID
from synapse.util.async import run_on_reactor from synapse.util.async import run_on_reactor
from synapse.util.caches.expiringcache import ExpiringCache from synapse.util.caches.expiringcache import ExpiringCache
from synapse.util.logcontext import make_deferred_yieldable
from twisted.web.client import PartialDownloadError from twisted.web.client import PartialDownloadError
@ -714,7 +715,7 @@ class AuthHandler(BaseHandler):
if not lookupres: if not lookupres:
defer.returnValue(None) defer.returnValue(None)
(user_id, password_hash) = lookupres (user_id, password_hash) = lookupres
result = self.validate_hash(password, password_hash) result = yield self.validate_hash(password, password_hash)
if not result: if not result:
logger.warn("Failed password login for user %s", user_id) logger.warn("Failed password login for user %s", user_id)
defer.returnValue(None) defer.returnValue(None)
@ -842,10 +843,13 @@ class AuthHandler(BaseHandler):
password (str): Password to hash. password (str): Password to hash.
Returns: Returns:
Hashed password (str). Deferred(str): Hashed password.
""" """
return bcrypt.hashpw(password.encode('utf8') + self.hs.config.password_pepper, def _do_hash():
bcrypt.gensalt(self.bcrypt_rounds)) 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): def validate_hash(self, password, stored_hash):
"""Validates that self.hash(password) == stored_hash. """Validates that self.hash(password) == stored_hash.
@ -855,13 +859,17 @@ class AuthHandler(BaseHandler):
stored_hash (str): Expected hash value. stored_hash (str): Expected hash value.
Returns: 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, return bcrypt.hashpw(password.encode('utf8') + self.hs.config.password_pepper,
stored_hash.encode('utf8')) == stored_hash stored_hash.encode('utf8')) == stored_hash
if stored_hash:
return make_deferred_yieldable(threads.deferToThread(_do_validate_hash))
else: else:
return False return defer.succeed(False)
class MacaroonGeneartor(object): class MacaroonGeneartor(object):

View file

@ -131,7 +131,7 @@ class RegistrationHandler(BaseHandler):
yield run_on_reactor() yield run_on_reactor()
password_hash = None password_hash = None
if password: if password:
password_hash = self.auth_handler().hash(password) password_hash = yield self.auth_handler().hash(password)
if localpart: if localpart:
yield self.check_username(localpart, guest_access_token=guest_access_token) yield self.check_username(localpart, guest_access_token=guest_access_token)

View file

@ -31,7 +31,7 @@ class SetPasswordHandler(BaseHandler):
@defer.inlineCallbacks @defer.inlineCallbacks
def set_password(self, user_id, newpassword, requester=None): 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_device_id = requester.device_id if requester else None
except_access_token_id = requester.access_token_id if requester else None except_access_token_id = requester.access_token_id if requester else None