diff options
| author | Eli Collins <elic@astllc.org> | 2011-03-25 12:11:17 -0400 |
|---|---|---|
| committer | Eli Collins <elic@astllc.org> | 2011-03-25 12:11:17 -0400 |
| commit | 32773d53f07bd9e94d4966a28f48c56cdecd51c3 (patch) | |
| tree | 59f64c35fb6c4b3255882a417b9a4462c40cac8f /passlib | |
| parent | 771a8d2c0f909c6e8a59ff39ee4a1e939d799ce9 (diff) | |
| download | passlib-32773d53f07bd9e94d4966a28f48c56cdecd51c3.tar.gz | |
misc bugfixes & tweaks for win32 compat
Diffstat (limited to 'passlib')
| -rw-r--r-- | passlib/apps.py | 6 | ||||
| -rw-r--r-- | passlib/handlers/bcrypt.py | 2 | ||||
| -rw-r--r-- | passlib/handlers/des_crypt.py | 2 | ||||
| -rw-r--r-- | passlib/handlers/md5_crypt.py | 2 | ||||
| -rw-r--r-- | passlib/handlers/sha2_crypt.py | 4 | ||||
| -rw-r--r-- | passlib/tests/test_context.py | 7 | ||||
| -rw-r--r-- | passlib/tests/test_drivers.py | 4 | ||||
| -rw-r--r-- | passlib/tests/test_utils.py | 7 | ||||
| -rw-r--r-- | passlib/tests/test_utils_handlers.py | 18 | ||||
| -rw-r--r-- | passlib/utils/__init__.py | 5 | ||||
| -rw-r--r-- | passlib/utils/pbkdf2.py | 12 |
11 files changed, 45 insertions, 24 deletions
diff --git a/passlib/apps.py b/passlib/apps.py index 5b84963..ed91f2f 100644 --- a/passlib/apps.py +++ b/passlib/apps.py @@ -3,12 +3,12 @@ #imports #========================================================= #core -import platform import logging; log = logging.getLogger(__name__) #site #libs from passlib import hash from passlib.context import CryptContext +from passlib.utils import sys_bits #pkg #local __all__ = [ @@ -23,8 +23,6 @@ __all__ = [ #========================================================= #for quickly bootstrapping new custom applications #========================================================= -_is32 = platform.architecture()[0] == '32bit' - custom_app_context = CryptContext( #choose some reasonbly strong schemes schemes=["sha512_crypt", "sha256_crypt"], @@ -32,7 +30,7 @@ custom_app_context = CryptContext( #set some useful global options min_verify_time = .125, all__vary_rounds = "10%", - default="sha256_crypt" if _is32 else "sha512_crypt", + default="sha256_crypt" if sys_bits < 64 else "sha512_crypt", #set a good starting point for rounds selection sha512_crypt__default_rounds = 40000, diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py index 45a3077..ff386b1 100644 --- a/passlib/handlers/bcrypt.py +++ b/passlib/handlers/bcrypt.py @@ -140,7 +140,7 @@ class bcrypt(MultiBackendHandler): @classproperty def _has_backend_os_crypt(cls): return ( - os_crypt + os_crypt is not None and os_crypt("test", "$2a$04$......................") == '$2a$04$......................qiOQjkB8hxU8OzRhS.GhRMa4VUnkPty' diff --git a/passlib/handlers/des_crypt.py b/passlib/handlers/des_crypt.py index ac9da21..e358208 100644 --- a/passlib/handlers/des_crypt.py +++ b/passlib/handlers/des_crypt.py @@ -200,7 +200,7 @@ class des_crypt(MultiBackendHandler): @classproperty def _has_backend_os_crypt(cls): - return os_crypt and os_crypt("test", "ab") == 'abgOeLfPimXQo' + return os_crypt is not None and os_crypt("test", "ab") == 'abgOeLfPimXQo' def _calc_checksum_builtin(self, secret): #forbidding nul chars because linux crypt (and most C implementations) won't accept it either. diff --git a/passlib/handlers/md5_crypt.py b/passlib/handlers/md5_crypt.py index 07081a0..c7ce561 100644 --- a/passlib/handlers/md5_crypt.py +++ b/passlib/handlers/md5_crypt.py @@ -195,7 +195,7 @@ class md5_crypt(MultiBackendHandler): @classproperty def _has_backend_os_crypt(cls): - return os_crypt and os_crypt("test", "$1$test") == '$1$test$pi/xDtU5WFVRqYS6BMU8X/' + return os_crypt is not None and os_crypt("test", "$1$test") == '$1$test$pi/xDtU5WFVRqYS6BMU8X/' def _calc_checksum_builtin(self, secret): #FIXME: can't find definitive policy on how md5-crypt handles non-ascii. diff --git a/passlib/handlers/sha2_crypt.py b/passlib/handlers/sha2_crypt.py index e15203c..c430d09 100644 --- a/passlib/handlers/sha2_crypt.py +++ b/passlib/handlers/sha2_crypt.py @@ -321,7 +321,7 @@ class sha256_crypt(MultiBackendHandler): @classproperty def _has_backend_os_crypt(cls): return bool( - os_crypt and + os_crypt is not None and os_crypt("test", "$5$rounds=1000$test") == "$5$rounds=1000$test$QmQADEXMG8POI5WDsaeho0P36yK3Tcrgboabng6bkb/" ) @@ -468,7 +468,7 @@ class sha512_crypt(MultiBackendHandler): @classproperty def _has_backend_os_crypt(cls): return bool( - os_crypt and + os_crypt is not None and os_crypt("test", "$6$rounds=1000$test") == "$6$rounds=1000$test$2M/Lx6MtobqjLjobw0Wmo4Q5OFx5nVLJvmgseatA6oMnyWeBdRDx4DU.1H3eGmse6pgsOgDisWBGI5c7TZauS0" ) diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index df9b78d..2543709 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -674,16 +674,19 @@ class CryptContextTest(TestCase): def test_24_min_verify_time(self): cc = CryptContext(["plaintext", "bsdi_crypt"], min_verify_time=.1) + #plaintext should (in reality) take <.01, + #so this test checks mvt makes it take 0.09 - .5 s = time.time() cc.verify("password", "password") d = time.time()-s self.assertTrue(d>=.09,d) self.assertTrue(d<.5) - + + #this may take longer, so we just check min s = time.time() cc.verify("password", '_2b..iHVSUNMkJT.GcFU') d = time.time()-s - self.assertTrue(d>=.1) + self.assertTrue(d>=.09, "mvt=.1, delta=%r" % (d,)) #========================================================= #eoc diff --git a/passlib/tests/test_drivers.py b/passlib/tests/test_drivers.py index 32e3823..3c9ce67 100644 --- a/passlib/tests/test_drivers.py +++ b/passlib/tests/test_drivers.py @@ -246,7 +246,9 @@ class LdapSaltedSha1Test(HandlerCase): class LdapPlaintextTest(HandlerCase): handler = ldap_digests.ldap_plaintext known_correct_hashes = [ ("password", 'password') ] - known_unidentified_hashes = [ "{MD5}fooey" ] + known_unidentified_hashes = [ "{FOO}bar" ] + + known_other_hashes = [ ("ldap_md5", "{MD5}/F4DjTilcDIIVEHn/nAQsA==")] # helloworld -> '{CRYPT}dQ58WW.1980Ig' diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index 40a64f4..4f31ebb 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -11,7 +11,7 @@ import random #module from passlib import utils from passlib.context import CryptContext -from passlib.utils import h64, des, Undef +from passlib.utils import h64, des, Undef, sys_bits from passlib.utils.md4 import md4 from passlib.tests.utils import TestCase, Params as ak, enable_option @@ -412,6 +412,9 @@ class _Pbkdf2BackendTest(TestCase): if not self.enable_m2crypto: self._orig_EVP = pbkdf2._EVP pbkdf2._EVP = None + else: + #set flag so tests can check for m2crypto presence quickly + self.enable_m2crypto = bool(pbkdf2._EVP) def tearDown(self): if not self.enable_m2crypto: @@ -473,7 +476,7 @@ class _Pbkdf2BackendTest(TestCase): self.assertRaises(TypeError, pbkdf2.pbkdf2, 'password', 'salt', 'x', 16) #invalid keylen - self.assertRaises(ValueError, pbkdf2.pbkdf2, 'password', 'salt', 1, 20*(2**32)) + self.assertRaises(ValueError, pbkdf2.pbkdf2, 'password', 'salt', 1, 20*(2**32-1)+1) #invalid salt type self.assertRaises(TypeError, pbkdf2.pbkdf2, 'password', 5, 1, 10) diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index d9e05c6..1750113 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -139,7 +139,7 @@ class SkeletonTest(TestCase): #check small & large rounds with catch_warnings(): - warnings.filterwarnings("ignore", ".* does not allow (less|greater) than 1 rounds: .*", UserWarning) + warnings.filterwarnings("ignore", ".* does not allow (less|more) than \d rounds: .*", UserWarning) self.assertEqual(d1.norm_rounds(0), 1) self.assertEqual(d1.norm_rounds(4), 3) self.assertRaises(ValueError, d1.norm_rounds, 0, strict=True) @@ -167,7 +167,7 @@ class SkeletonTest(TestCase): backends = ("a", "b") _has_backend_a = False - _has_backend_b = True + _has_backend_b = False def _calc_checksum_a(self, secret): return 'a' @@ -175,6 +175,13 @@ class SkeletonTest(TestCase): def _calc_checksum_b(self, secret): return 'b' + #test no backends + self.assertRaises(EnvironmentError, d1.set_backend, 'default') + self.assertFalse(d1.has_backend()) + + #enable 'b' backend + d1._has_backend_b = True + #test lazy load obj = d1() self.assertEquals(obj.calc_checksum('s'), 'b') @@ -187,13 +194,10 @@ class SkeletonTest(TestCase): #test unavailable self.assertRaises(ValueError, d1.set_backend, 'a') - #test all unavailable - d1._has_backend_b = False - self.assertRaises(EnvironmentError, d1.set_backend, 'default') - self.assertFalse(d1.has_backend()) + #enable 'a' backend also + d1._has_backend_a = True #test explicit - d1._has_backend_a = d1._has_backend_b = True self.assertTrue(d1.has_backend()) d1.set_backend('a') self.assertEquals(obj.calc_checksum('s'), 'a') diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index 00f27da..8b7fff2 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -7,6 +7,7 @@ from cStringIO import StringIO from functools import update_wrapper from hashlib import sha256 import logging; log = logging.getLogger(__name__) +from math import log as logb import os import sys import random @@ -40,6 +41,10 @@ __all__ = [ 'getrandstr', ] +#quick check of system's arch +sys_bits = int(logb(sys.maxsize,2)+1.5) +assert sys_bits in (32,64), "unexpected sys_bits value: %r" % (sys_bits,) + #================================================================================= #os crypt helpers #================================================================================= diff --git a/passlib/utils/pbkdf2.py b/passlib/utils/pbkdf2.py index ad6f087..460925c 100644 --- a/passlib/utils/pbkdf2.py +++ b/passlib/utils/pbkdf2.py @@ -48,6 +48,7 @@ if _EVP: #backend #================================================================================= MAX_BLOCKS = 0xffffffffL #2**32-1 +MAX_HMAC_SHA1_KEYLEN = MAX_BLOCKS*20 def _resolve_prf(prf): "resolve prf string or callable -> func & digest_size" @@ -134,10 +135,15 @@ def pbkdf2(secret, salt, rounds, keylen, prf="hmac-sha1"): #special case for m2crypto + hmac-sha1 if prf == "hmac-sha1" and _EVP: - try: - return _EVP.pbkdf2(secret, salt, rounds, keylen) - except OverflowError: + #NOTE: doing check here, because M2crypto won't take longs (which this is, under 32bit) + if keylen > MAX_HMAC_SHA1_KEYLEN: raise ValueError, "key length too long" + + #NOTE: M2crypto reliably segfaults for me if given keylengths + # larger than 40 (crashes at 41 on one system, 61 on another). + # so just avoiding it for longer calls. + if keylen < 41: + return _EVP.pbkdf2(secret, salt, rounds, keylen) #resolve prf encode_block, digest_size = _resolve_prf(prf) |
