summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2020-05-12 11:16:10 -0400
committerEli Collins <elic@assurancetechnologies.com>2020-05-12 11:16:10 -0400
commitf5fdab0d18757b9952799eb1956a970773adddaa (patch)
tree2d53e23f6cfd812cb6dfddf7615801efb1c07fb8
parent6bba63a8d801f413154f523cc2c3e899af243cc8 (diff)
downloadpasslib-f5fdab0d18757b9952799eb1956a970773adddaa.tar.gz
bugfix: bcrypt os_crypt backend wasn't being detected properly under py3;
due to a few interlocking issues. passlib.utils: test_crypt() shouldn't accept hash=<bytes>, because equality comparison with str will always fail under py3. * test_crypt() now enforces hash=<unicode_or_str> as input. it previously allowed hash=bytes, but equality comparison with unicode (output by safe_crypt) would always return False under python 3. * bcrypt's TEST_HASH_2A constant was stored bytes, which was causing os_crypt detection to fail due to test_crypt() bug above. changed to use native str. sidewnote: this would have been caught by UTs, except for bug in test_82_crypt_support() that was fixed in rev 43bae3f786b7.
-rw-r--r--docs/history/1.7.rst5
-rw-r--r--passlib/handlers/bcrypt.py6
-rw-r--r--passlib/utils/__init__.py10
3 files changed, 16 insertions, 5 deletions
diff --git a/docs/history/1.7.rst b/docs/history/1.7.rst
index 49b452a..5d8ff44 100644
--- a/docs/history/1.7.rst
+++ b/docs/history/1.7.rst
@@ -36,6 +36,11 @@ Bugfixes
plain SHA256. This should strengthen the hash against brute-force attempts which bypass
the intermediary hash by using known-sha256-digest lookup tables (:issue:`114`).
+* .. py:currentmodule:: passlib.hash
+
+ :class:`bcrypt`: OS native backend wasn't being detected under Python 3 on BSD platforms.
+ This was due to an internal issue in feature-detection code, which has been fixed.
+
* :func:`passlib.utils.safe_crypt`: Support :func:`crypt.crypt` unexpectedly
returning bytes under Python 3 (:issue:`113`).
diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py
index 73fbc21..e54a085 100644
--- a/passlib/handlers/bcrypt.py
+++ b/passlib/handlers/bcrypt.py
@@ -49,7 +49,7 @@ IDENT_2B = u("$2b$")
_BNULL = b'\x00'
# reference hash of "test", used in various self-checks
-TEST_HASH_2A = b"$2a$04$5BJqKfqMQvV7nS.yUguNcueVirQqDBGaLXSqj.rs.pZPlNR0UX/HK"
+TEST_HASH_2A = "$2a$04$5BJqKfqMQvV7nS.yUguNcueVirQqDBGaLXSqj.rs.pZPlNR0UX/HK"
def _detect_pybcrypt():
"""
@@ -408,7 +408,7 @@ class _BcryptCommon(uh.SubclassBackendMixin, uh.TruncateMixin, uh.HasManyIdents,
#----------------------------------------------------------------
# check for 2y support
#----------------------------------------------------------------
- test_hash_2y = TEST_HASH_2A.replace(b"2a", b"2y")
+ test_hash_2y = TEST_HASH_2A.replace("2a", "2y")
result = safe_verify("test", test_hash_2y)
if not result:
raise RuntimeError("%s incorrectly rejected $2y$ hash" % backend)
@@ -428,7 +428,7 @@ class _BcryptCommon(uh.SubclassBackendMixin, uh.TruncateMixin, uh.HasManyIdents,
#----------------------------------------------------------------
# check for 2b support
#----------------------------------------------------------------
- test_hash_2b = TEST_HASH_2A.replace(b"2a", b"2b")
+ test_hash_2b = TEST_HASH_2A.replace("2a", "2b")
result = safe_verify("test", test_hash_2b)
if not result:
raise RuntimeError("%s incorrectly rejected $2b$ hash" % backend)
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py
index ba54b2f..b9fad4d 100644
--- a/passlib/utils/__init__.py
+++ b/passlib/utils/__init__.py
@@ -59,7 +59,7 @@ from passlib.exc import ExpectedStringError
from passlib.utils.compat import (add_doc, join_bytes, join_byte_values,
join_byte_elems, irange, imap, PY3, u,
join_unicode, unicode, byte_elem_value, nextgetter,
- unicode_or_bytes_types,
+ unicode_or_str, unicode_or_bytes_types,
get_method_function, suppress_cause)
# local
__all__ = [
@@ -860,7 +860,13 @@ def test_crypt(secret, hash):
:arg hash: known hash of password to use as reference
:returns: True or False
"""
- assert secret and hash
+ # safe_crypt() always returns unicode, which means that for py3,
+ # 'hash' can't be bytes, or "== hash" will never be True.
+ # under py2 unicode & str(bytes) will compare fine;
+ # so just enforcing "unicode_or_str" limitation
+ assert isinstance(hash, unicode_or_str), \
+ "hash must be unicode_or_str, got %s" % type(hash)
+ assert hash, "hash must be non-empty"
return safe_crypt(secret, hash) == hash
timer = timeit.default_timer