summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2020-10-06 15:56:15 -0400
committerEli Collins <elic@assurancetechnologies.com>2020-10-06 15:56:15 -0400
commit73ab1733ebe4813063ecf96ba9fca028392db7ff (patch)
treeca37eb4fe3717cb72c5e50864804dcc0bc43da45
parent49eb92ea545e69184bbea041d979325b2c715600 (diff)
downloadpasslib-73ab1733ebe4813063ecf96ba9fca028392db7ff.tar.gz
passlib.hash.bcrypt: remove support for "py-bcrypt" backend
-rw-r--r--passlib/handlers/bcrypt.py73
-rw-r--r--passlib/tests/test_handlers_bcrypt.py36
-rw-r--r--tox.ini3
3 files changed, 1 insertions, 111 deletions
diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py
index c153dc4..7a57d47 100644
--- a/passlib/handlers/bcrypt.py
+++ b/passlib/handlers/bcrypt.py
@@ -19,7 +19,6 @@ import logging; log = logging.getLogger(__name__)
from warnings import warn
# site
_bcrypt = None # dynamically imported by _load_backend_bcrypt()
-_pybcrypt = None # dynamically imported by _load_backend_pybcrypt()
# pkg
_builtin_bcrypt = None # dynamically imported by _load_backend_builtin()
from passlib.crypto.digest import compile_hmac
@@ -651,75 +650,6 @@ class _BcryptBackend(_BcryptCommon):
raise uh.exc.CryptBackendError(self, config, hash, source="`bcrypt` package")
return hash[-31:].decode("ascii")
-#-----------------------------------------------------------------------
-# pybcrypt backend
-#-----------------------------------------------------------------------
-class _PyBcryptBackend(_BcryptCommon):
- """
- backend which uses 'pybcrypt' package
- """
-
- #: classwide thread lock used for pybcrypt < 0.3
- _calc_lock = None
-
- @classmethod
- def _load_backend_mixin(mixin_cls, name, dryrun):
- # try to import pybcrypt
- global _pybcrypt
- if not _detect_pybcrypt():
- # not installed, or bcrypt installed instead
- return False
- try:
- import bcrypt as _pybcrypt
- except ImportError: # pragma: no cover
- # XXX: should we raise AssertionError here? (if get here, _detect_pybcrypt() is broken)
- return False
-
- # deprecated as of 1.7.2
- if not dryrun:
- warn("Support for `py-bcrypt` is deprecated, and will be removed in Passlib 1.8; "
- "Please use `pip install bcrypt` instead", DeprecationWarning)
-
- # determine pybcrypt version
- try:
- version = _pybcrypt._bcrypt.__version__
- except:
- log.warning("(trapped) error reading pybcrypt version", exc_info=True)
- version = "<unknown>"
- log.debug("detected 'pybcrypt' backend, version %r", version)
-
- # return calc function based on version
- vinfo = parse_version(version) or (0, 0)
- if vinfo < (0, 3):
- warn("py-bcrypt %s has a major security vulnerability, "
- "you should upgrade to py-bcrypt 0.3 immediately."
- % version, uh.exc.PasslibSecurityWarning)
- if mixin_cls._calc_lock is None:
- import threading
- mixin_cls._calc_lock = threading.Lock()
- mixin_cls._calc_checksum = mixin_cls._calc_checksum_threadsafe
-
- return mixin_cls._finalize_backend_mixin(name, dryrun)
-
- def _calc_checksum_threadsafe(self, secret):
- # as workaround for pybcrypt < 0.3's concurrency issue,
- # we wrap everything in a thread lock. as long as bcrypt is only
- # used through passlib, this should be safe.
- with self._calc_lock:
- return self._calc_checksum_raw(secret)
-
- def _calc_checksum_raw(self, secret):
- # py-bcrypt behavior:
- # py3: unicode secret encoded as utf-8 bytes,
- # hash encoded as ascii bytes, returns ascii unicode.
- secret, ident = self._prepare_digest_args(secret)
- config = self._get_config(ident)
- hash = _pybcrypt.hashpw(secret, config)
- if not hash.startswith(config) or len(hash) != len(config) + 31:
- raise uh.exc.CryptBackendError(self, config, hash, source="pybcrypt library")
- return hash[-31:]
-
- _calc_checksum = _calc_checksum_raw
#-----------------------------------------------------------------------
# os crypt backend
@@ -898,7 +828,7 @@ class bcrypt(_NoBackend, _BcryptCommon):
# in order to load the appropriate backend.
#: list of potential backends
- backends = ("bcrypt", "pybcrypt", "os_crypt", "builtin")
+ backends = ("bcrypt", "os_crypt", "builtin")
#: flag that this class's bases should be modified by SubclassBackendMixin
_backend_mixin_target = True
@@ -907,7 +837,6 @@ class bcrypt(_NoBackend, _BcryptCommon):
_backend_mixin_map = {
None: _NoBackend,
"bcrypt": _BcryptBackend,
- "pybcrypt": _PyBcryptBackend,
"os_crypt": _OsCryptBackend,
"builtin": _BuiltinBackend,
}
diff --git a/passlib/tests/test_handlers_bcrypt.py b/passlib/tests/test_handlers_bcrypt.py
index 54a3bc1..683b9ba 100644
--- a/passlib/tests/test_handlers_bcrypt.py
+++ b/passlib/tests/test_handlers_bcrypt.py
@@ -200,7 +200,6 @@ class _bcrypt_test(HandlerCase):
fuzz_verifiers = HandlerCase.fuzz_verifiers + (
"fuzz_verifier_bcrypt",
- "fuzz_verifier_pybcrypt",
)
def fuzz_verifier_bcrypt(self):
@@ -235,39 +234,6 @@ class _bcrypt_test(HandlerCase):
raise ValueError("bcrypt rejected hash: %r (secret=%r)" % (hash, secret))
return check_bcrypt
- def fuzz_verifier_pybcrypt(self):
- # test against py-bcrypt, if available
- from passlib.handlers.bcrypt import (
- IDENT_2, IDENT_2A, IDENT_2B, IDENT_2X, IDENT_2Y,
- _PyBcryptBackend,
- )
- from passlib.utils import to_native_str
-
- loaded = _PyBcryptBackend._load_backend_mixin("pybcrypt", False)
- if not loaded:
- return
-
- from passlib.handlers.bcrypt import _pybcrypt as bcrypt_mod
-
- lock = _PyBcryptBackend._calc_lock # reuse threadlock workaround for pybcrypt 0.2
-
- def check_pybcrypt(secret, hash):
- """pybcrypt"""
- secret = to_native_str(secret, self.FuzzHashGenerator.password_encoding)
- if len(secret) > 200: # vulnerable to wraparound bug
- secret = secret[:200]
- if hash.startswith((IDENT_2B, IDENT_2Y)):
- hash = IDENT_2A + hash[4:]
- try:
- if lock:
- with lock:
- return bcrypt_mod.hashpw(secret, hash) == hash
- else:
- return bcrypt_mod.hashpw(secret, hash) == hash
- except ValueError:
- raise ValueError("py-bcrypt rejected hash: %r" % (hash,))
- return check_pybcrypt
-
class FuzzHashGenerator(HandlerCase.FuzzHashGenerator):
@@ -400,7 +366,6 @@ class _bcrypt_test(HandlerCase):
# create test cases for specific backends
bcrypt_bcrypt_test = _bcrypt_test.create_backend_case("bcrypt")
-bcrypt_pybcrypt_test = _bcrypt_test.create_backend_case("pybcrypt")
class bcrypt_os_crypt_test(_bcrypt_test.create_backend_case("os_crypt")):
@@ -645,7 +610,6 @@ class _bcrypt_sha256_test(HandlerCase):
# create test cases for specific backends
bcrypt_sha256_bcrypt_test = _bcrypt_sha256_test.create_backend_case("bcrypt")
-bcrypt_sha256_pybcrypt_test = _bcrypt_sha256_test.create_backend_case("pybcrypt")
class bcrypt_sha256_os_crypt_test(_bcrypt_sha256_test.create_backend_case("os_crypt")):
diff --git a/tox.ini b/tox.ini
index 6b4ba2c..1a24f21 100644
--- a/tox.ini
+++ b/tox.ini
@@ -58,9 +58,7 @@ envlist =
pbkdf2-frombytes-py{3,py3},
# bcrypt backend testing (bcrypt cffi tested by default test)
- # NOTE: 'other' checks bcryptor & py-bcrypt
## bcrypthash-bcrypt-py{2,3,py,py3}, # tested by default config
- bcrypthash-other-py3
bcrypthash-{builtin,disabled}-py{3,py3}
# scrypt backend testing (builtin backend tested by default test)
@@ -156,7 +154,6 @@ deps =
# NOTE: bcrypt10 env disabled, just used to check legacy issues
## bcrypthash-bcrypt10: bcrypt<1.1
default,bcrypthash-bcrypt: bcrypt
- bcrypthash-other: py-bcrypt
# scrypt backend tests
# XXX: would test 'scrypt' under default, but not compatible w/ pypy,