summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-04-30 23:02:11 -0400
committerEli Collins <elic@assurancetechnologies.com>2012-04-30 23:02:11 -0400
commit176153315bbd4ae3ec8542a5fc6704041d7de342 (patch)
tree8f555a4a9a44f9cfc0ee4706b588d5cc579acf55
parent80c90ea391d20188f5f46de30ad32117f8b7258b (diff)
downloadpasslib-176153315bbd4ae3ec8542a5fc6704041d7de342.tar.gz
removed annoying builtin-bcrypt warning, decreased rounds on some test vectors for speed
-rw-r--r--docs/lib/passlib.hash.bcrypt.rst9
-rw-r--r--passlib/handlers/bcrypt.py14
-rw-r--r--passlib/tests/test_apps.py2
-rw-r--r--passlib/tests/test_handlers.py107
-rw-r--r--passlib/tests/test_hosts.py2
5 files changed, 69 insertions, 65 deletions
diff --git a/docs/lib/passlib.hash.bcrypt.rst b/docs/lib/passlib.hash.bcrypt.rst
index cb09e37..70c6341 100644
--- a/docs/lib/passlib.hash.bcrypt.rst
+++ b/docs/lib/passlib.hash.bcrypt.rst
@@ -50,11 +50,10 @@ Interface
(primarily BSD-derived systems).
4. A *slow* pure-python implementation of BCrypt, built into Passlib.
- It should be noted that the builtin pure-python implementation is too slow
- to be both secure and responsive at the same time (except under PyPy > 1.7)
- Because of this, it is disabled by default, unless
- the environment variable ``PASSLIB_BUILTIN_BCRYPT="enabled"`` has been set
- before Passlib is first loaded.
+ It should be noted that the pure-python implementation (#4) is too slow
+ to be useable, given the number of rounds currently required for security.
+ Because of this, it is disabled by default, unless the environment variable
+ ``PASSLIB_BUILTIN_BCRYPT="enabled"`` is set before Passlib is first loaded.
If the first three backends are not available, and the builtin
backend has not been enabled, :meth:`encrypt` and :meth:`verify`
diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py
index 77a99da..5086b36 100644
--- a/passlib/handlers/bcrypt.py
+++ b/passlib/handlers/bcrypt.py
@@ -26,7 +26,7 @@ try:
except ImportError: #pragma: no cover
bcryptor_engine = None
#libs
-from passlib.exc import PasslibHashWarning, PasslibSecurityWarning
+from passlib.exc import PasslibHashWarning
from passlib.utils import bcrypt64, safe_crypt, repeat_string, \
classproperty, rng, getrandstr, test_crypt
from passlib.utils.compat import bytes, b, u, uascii_to_str, unicode, str_to_uascii
@@ -189,8 +189,10 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
assert salt is not None, "HasSalt didn't generate new salt!"
changed, salt = bcrypt64.check_repair_unused(salt)
if changed:
+ # FIXME: if salt was provided by user, this message won't be
+ # correct. not sure if we want to throw error, or use different warning.
warn(
- "encountered a bcrypt hash with incorrectly set padding bits; "
+ "encountered a bcrypt salt with incorrectly set padding bits; "
"you may want to use bcrypt.normhash() "
"to fix this; see Passlib 1.5.3 changelog.",
PasslibHashWarning)
@@ -239,8 +241,7 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
@classmethod
def _no_backends_msg(cls):
- return "no bcrypt backends available - please install 'py-bcrypt' or " \
- "'bcryptor' for bcrypt support"
+ return "no bcrypt backends available - please install py-bcrypt"
def _calc_checksum_os_crypt(self, secret):
config = self._get_config()
@@ -300,11 +301,6 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
return str_to_uascii(hash[-31:])
def _calc_checksum_builtin(self, secret):
- # XXX: silence this warnings under pypy1.7? it's almost fast enough.
- warn("SECURITY WARNING: Passlib is using it's pure-python bcrypt "
- "implementation, which is TOO SLOW FOR PRODUCTION USE. It is "
- "strongly recommended that you install py-bcrypt or bcryptor for "
- "Passlib to use instead.", PasslibSecurityWarning)
if isinstance(secret, unicode):
secret = secret.encode("utf-8")
if _BNULL in secret:
diff --git a/passlib/tests/test_apps.py b/passlib/tests/test_apps.py
index 1758c38..5632087 100644
--- a/passlib/tests/test_apps.py
+++ b/passlib/tests/test_apps.py
@@ -90,7 +90,7 @@ class AppsTest(TestCase):
]:
self.assertTrue(ctx.verify("test", hash))
- h1 = '$2a$10$Ljj0Kgu7Ddob9xWoqzn0ae.uNfxPRofowWdksk.6jCUHKTGYLD.QG'
+ h1 = "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS"
if hashmod.bcrypt.has_backend():
self.assertTrue(ctx.verify("test", h1))
self.assertEqual(ctx.default_scheme(), "bcrypt")
diff --git a/passlib/tests/test_handlers.py b/passlib/tests/test_handlers.py
index b66cce1..a90daa3 100644
--- a/passlib/tests/test_handlers.py
+++ b/passlib/tests/test_handlers.py
@@ -189,25 +189,29 @@ class _bcrypt_test(HandlerCase):
#===============================================================
# override some methods
#===============================================================
- def setUpWarnings(self):
- super(_bcrypt_test, self).setUpWarnings()
- warnings.filterwarnings("ignore",
- "SECURITY WARNING: .*pure-python bcrypt.*")
-
- def do_genconfig(self, **kwds):
- # override default to speed up tests
- kwds.setdefault("rounds", 5)
+ def setUp(self):
+ # ensure builtin is enabled for duration of test.
+ if TEST_MODE("full") and self.backend == "builtin":
+ key = "PASSLIB_BUILTIN_BCRYPT"
+ orig = os.environ.get(key)
+ if orig:
+ self.addCleanup(os.environ.__setitem__, key, orig)
+ else:
+ self.addCleanup(os.environ.__delitem__, key)
+ os.environ[key] = "enabled"
+ super(_bcrypt_test, self).setUp()
+
+ def populate_settings(self, kwds):
+ # builtin is still just way too slow.
+ if self.backend == "builtin":
+ kwds.setdefault("rounds", 4)
+
+ super(_bcrypt_test, self).populate_settings(kwds)
# correct unused bits in provided salts, to silence some warnings.
- if 'salt' in kwds:
+ if 'salt' in kwds and len(kwds['salt']) == 22:
from passlib.utils import bcrypt64
kwds['salt'] = bcrypt64.repair_unused(kwds['salt'])
- return self.handler.genconfig(**kwds)
-
- def do_encrypt(self, secret, **kwds):
- # override default to speed up tests
- kwds.setdefault("rounds", 5)
- return self.handler.encrypt(secret, **kwds)
#===============================================================
# fuzz testing
@@ -282,23 +286,30 @@ class _bcrypt_test(HandlerCase):
# password, bad hash, good hash
# 2 bits of salt padding set
- ("loppux",
- "$2a$12$oaQbBqq8JnSM1NHRPQGXORm4GCUMqp7meTnkft4zgSnrbhoKdDV0C",
- "$2a$12$oaQbBqq8JnSM1NHRPQGXOOm4GCUMqp7meTnkft4zgSnrbhoKdDV0C"),
+# ("loppux", # \/
+# "$2a$12$oaQbBqq8JnSM1NHRPQGXORm4GCUMqp7meTnkft4zgSnrbhoKdDV0C",
+# "$2a$12$oaQbBqq8JnSM1NHRPQGXOOm4GCUMqp7meTnkft4zgSnrbhoKdDV0C"),
+ ("test", # \/
+ '$2a$04$oaQbBqq8JnSM1NHRPQGXORY4Vw3bdHKLIXTecPDRAcJ98cz1ilveO',
+ '$2a$04$oaQbBqq8JnSM1NHRPQGXOOY4Vw3bdHKLIXTecPDRAcJ98cz1ilveO'),
# all 4 bits of salt padding set
- ("Passlib11",
- "$2a$12$M8mKpW9a2vZ7PYhq/8eJVcUtKxpo6j0zAezu0G/HAMYgMkhPu4fLK",
- "$2a$12$M8mKpW9a2vZ7PYhq/8eJVOUtKxpo6j0zAezu0G/HAMYgMkhPu4fLK"),
+# ("Passlib11", # \/
+# "$2a$12$M8mKpW9a2vZ7PYhq/8eJVcUtKxpo6j0zAezu0G/HAMYgMkhPu4fLK",
+# "$2a$12$M8mKpW9a2vZ7PYhq/8eJVOUtKxpo6j0zAezu0G/HAMYgMkhPu4fLK"),
+ ("test", # \/
+ "$2a$04$yjDgE74RJkeqC0/1NheSScrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS",
+ "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS"),
# bad checksum padding
- ("test",
+ ("test", # \/
"$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIV",
"$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS"),
]
def test_90_bcrypt_padding(self):
"test passlib correctly handles bcrypt padding bits"
+ self.require_TEST_MODE("full")
#
# prevents reccurrence of issue 25 (https://code.google.com/p/passlib/issues/detail?id=25)
# were some unused bits were incorrectly set in bcrypt salt strings.
@@ -319,42 +330,40 @@ class _bcrypt_test(HandlerCase):
for i in irange(3):
check_padding(bcrypt.encrypt("bob", rounds=bcrypt.min_rounds))
- # some things that will raise warnings
- with catch_warnings(record=True) as wlog:
- #
- # test genconfig() corrects invalid salts & issues warning.
- #
+ #
+ # test genconfig() corrects invalid salts & issues warning.
+ #
+ with self.assertWarningList(["salt too large", corr_desc]):
hash = bcrypt.genconfig(salt="."*21 + "A.", rounds=5, relaxed=True)
- self.consumeWarningList(wlog, ["salt too large", corr_desc])
- self.assertEqual(hash, "$2a$05$" + "." * 22)
-
- #
- # make sure genhash() corrects input
- #
- samples = self.known_incorrect_padding
- for pwd, bad, good in samples:
+ self.assertEqual(hash, "$2a$05$" + "." * 22)
+
+ #
+ # make sure genhash() corrects input
+ #
+ samples = self.known_incorrect_padding
+ for pwd, bad, good in samples:
+ with self.assertWarningList([corr_desc]):
self.assertEqual(bcrypt.genhash(pwd, bad), good)
- self.consumeWarningList(wlog, [corr_desc])
+ with self.assertWarningList([]):
self.assertEqual(bcrypt.genhash(pwd, good), good)
- self.consumeWarningList(wlog)
- #
- # and that verify() works good & bad
- #
+ #
+ # and that verify() works good & bad
+ #
+ with self.assertWarningList([corr_desc]):
self.assertTrue(bcrypt.verify(pwd, bad))
- self.consumeWarningList(wlog, [corr_desc])
+ with self.assertWarningList([]):
self.assertTrue(bcrypt.verify(pwd, good))
- self.consumeWarningList(wlog)
- #
- # test normhash cleans things up correctly
- #
- for pwd, bad, good in samples:
+ #
+ # test normhash cleans things up correctly
+ #
+ for pwd, bad, good in samples:
+ with self.assertWarningList([corr_desc]):
self.assertEqual(bcrypt.normhash(bad), good)
- self.consumeWarningList(wlog, [corr_desc])
+ with self.assertWarningList([]):
self.assertEqual(bcrypt.normhash(good), good)
- self.consumeWarningList(wlog)
- self.assertEqual(bcrypt.normhash("$md5$abc"), "$md5$abc")
+ self.assertEqual(bcrypt.normhash("$md5$abc"), "$md5$abc")
hash.bcrypt._no_backends_msg() #call this for coverage purposes
diff --git a/passlib/tests/test_hosts.py b/passlib/tests/test_hosts.py
index 69408da..33b2451 100644
--- a/passlib/tests/test_hosts.py
+++ b/passlib/tests/test_hosts.py
@@ -61,7 +61,7 @@ class HostsTest(TestCase):
'kAJJz.Rwp0A/I',
]:
self.assertTrue(ctx.verify("test", hash))
- h1 = '$2a$10$Ljj0Kgu7Ddob9xWoqzn0ae.uNfxPRofowWdksk.6jCUHKTGYLD.QG'
+ h1 = "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS"
if hashmod.bcrypt.has_backend():
self.assertTrue(ctx.verify("test", h1))
else: