summaryrefslogtreecommitdiff
path: root/passlib/handlers
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-01-19 00:13:49 -0500
committerEli Collins <elic@assurancetechnologies.com>2012-01-19 00:13:49 -0500
commitbcf652e665ba2ffbf8e3f43b4e1108e7aa29dbb0 (patch)
tree3a2aff7abc0d80d9c560846622f89439634f25ce /passlib/handlers
parent6f816a3d7f1f3a394fedcc0aa410792a95b9ece6 (diff)
downloadpasslib-bcf652e665ba2ffbf8e3f43b4e1108e7aa29dbb0.tar.gz
simplified crypt.crypt() wrappers
* safe_crypt() improved - accepts unicode/bytes for salt, checks for NULL, returns None on failure * added test_crypt() wrapper to simplify backend checks. * removed native=True from most to_string() implementations, unused now. * updated UTs
Diffstat (limited to 'passlib/handlers')
-rw-r--r--passlib/handlers/bcrypt.py38
-rw-r--r--passlib/handlers/des_crypt.py46
-rw-r--r--passlib/handlers/md5_crypt.py9
-rw-r--r--passlib/handlers/pbkdf2.py8
-rw-r--r--passlib/handlers/sha1_crypt.py14
-rw-r--r--passlib/handlers/sha2_crypt.py36
-rw-r--r--passlib/handlers/sun_md5_crypt.py8
7 files changed, 75 insertions, 84 deletions
diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py
index 9a1f595..7a698d4 100644
--- a/passlib/handlers/bcrypt.py
+++ b/passlib/handlers/bcrypt.py
@@ -27,8 +27,8 @@ except ImportError: #pragma: no cover - though should run whole suite w/o bcrypt
bcryptor_engine = None
#libs
from passlib.exc import PasslibHandlerWarning
-from passlib.utils import BCRYPT_CHARS as BCHARS, safe_os_crypt, \
- classproperty, rng, getrandstr
+from passlib.utils import BCRYPT_CHARS as BCHARS, safe_crypt, \
+ classproperty, rng, getrandstr, test_crypt
from passlib.utils.compat import bytes, u, uascii_to_str, unicode
import passlib.utils.handlers as uh
@@ -144,9 +144,10 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
strict=strict and bool(chk),
)
- def to_string(self, native=True):
- hash = u("%s%02d$%s%s") % (self.ident, self.rounds, self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ def to_string(self):
+ hash = u("%s%02d$%s%s") % (self.ident, self.rounds, self.salt,
+ self.checksum or u(''))
+ return uascii_to_str(hash)
#=========================================================
# specialized salt generation - fixes passlib issue 25
@@ -228,18 +229,17 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
@classproperty
def _has_backend_os_crypt(cls):
- h1 = u('$2$04$......................1O4gOrCYaqBG3o/4LnT2ykQUt1wbyju')
- h2 = u('$2a$04$......................qiOQjkB8hxU8OzRhS.GhRMa4VUnkPty')
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h1)[1]==h1 and
- safe_os_crypt(u("test"), h2)[1]==h2)
+ h1 = '$2$04$......................1O4gOrCYaqBG3o/4LnT2ykQUt1wbyju'
+ h2 = '$2a$04$......................qiOQjkB8hxU8OzRhS.GhRMa4VUnkPty'
+ return test_crypt("test",h1) and test_crypt("test", h2)
@classmethod
def _no_backends_msg(cls):
return "no BCrypt backends available - please install pybcrypt or bcryptor for BCrypt support"
def _calc_checksum_os_crypt(self, secret):
- ok, hash = safe_os_crypt(secret, self.to_string(native=False))
- if ok:
+ hash = safe_crypt(secret, self.to_string())
+ if hash:
return hash[-31:]
else:
#NOTE: not checking backends since this is lowest priority,
@@ -249,26 +249,22 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh.
def _calc_checksum_pybcrypt(self, secret):
#pybcrypt behavior:
- # py2: unicode secret -> ascii bytes (we override this)
- # unicode hash -> ascii bytes (we provide ascii bytes)
- # returns ascii bytes
+ # py2: unicode secret/hash encoded as ascii bytes before use,
+ # bytes takes as-is; returns ascii bytes.
# py3: can't get to install
if isinstance(secret, unicode):
secret = secret.encode("utf-8")
- hash = pybcrypt_hashpw(secret,
- self.to_string(native=False))
+ hash = pybcrypt_hashpw(secret, self.to_string())
return hash[-31:].decode("ascii")
def _calc_checksum_bcryptor(self, secret):
#bcryptor behavior:
- # py2: unicode secret -> ascii bytes (we have to override)
- # unicode hash -> ascii bytes (we provide ascii bytes)
- # returns ascii bytes
+ # py2: unicode secret/hash encoded as ascii bytes before use,
+ # bytes takes as-is; returns ascii bytes.
# py3: can't get to install
if isinstance(secret, unicode):
secret = secret.encode("utf-8")
- hash = bcryptor_engine(False).hash_key(secret,
- self.to_string(native=False))
+ hash = bcryptor_engine(False).hash_key(secret, self.to_string())
return hash[-31:].decode("ascii")
def _calc_checksum_builtin(self, secret):
diff --git a/passlib/handlers/des_crypt.py b/passlib/handlers/des_crypt.py
index 976625a..b326e8e 100644
--- a/passlib/handlers/des_crypt.py
+++ b/passlib/handlers/des_crypt.py
@@ -58,7 +58,7 @@ import logging; log = logging.getLogger(__name__)
from warnings import warn
#site
#libs
-from passlib.utils import classproperty, h64, h64big, safe_os_crypt
+from passlib.utils import classproperty, h64, h64big, safe_crypt, test_crypt
from passlib.utils.compat import b, bytes, belem_ord, u, uascii_to_str, unicode
from passlib.utils.des import mdes_encrypt_int_block
import passlib.utils.handlers as uh
@@ -193,9 +193,9 @@ class des_crypt(uh.HasManyBackends, uh.HasSalt, uh.GenericHandler):
salt, chk = hash[:2], hash[2:]
return cls(salt=salt, checksum=chk or None, strict=bool(chk))
- def to_string(self, native=True):
+ def to_string(self):
hash = u("%s%s") % (self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
@@ -206,28 +206,23 @@ class des_crypt(uh.HasManyBackends, uh.HasSalt, uh.GenericHandler):
@classproperty
def _has_backend_os_crypt(cls):
- h = u('abgOeLfPimXQo')
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h)[1]==h)
+ return test_crypt("test", 'abgOeLfPimXQo')
def _calc_checksum_builtin(self, secret):
- #gotta do something - no official policy since des-crypt predates unicode
+ # gotta do something - no official policy since des-crypt predates unicode
if isinstance(secret, unicode):
secret = secret.encode("utf-8")
- #forbidding nul chars because linux crypt (and most C implementations) won't accept it either.
+ # forbidding nul chars because linux crypt (and most C implementations)
+ # won't accept it either.
if b('\x00') in secret:
raise ValueError("null char in secret")
return raw_crypt(secret, self.salt.encode("ascii")).decode("ascii")
def _calc_checksum_os_crypt(self, secret):
- #os_crypt() would raise less useful error
- null = u('\x00') if isinstance(secret, unicode) else b('\x00')
- if null in secret:
- raise ValueError("null char in secret")
-
- #NOTE: safe_os_crypt encodes unicode secret -> utf8
- #no official policy since des-crypt predates unicode
- ok, hash = safe_os_crypt(secret, self.salt)
- if ok:
+ # NOTE: safe_crypt encodes unicode secret -> utf8
+ # no official policy since des-crypt predates unicode
+ hash = safe_crypt(secret, self.salt)
+ if hash:
return hash[2:]
else:
return self._calc_checksum_builtin(secret)
@@ -321,10 +316,10 @@ class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
strict=bool(chk),
)
- def to_string(self, native=True):
+ def to_string(self):
hash = u("_%s%s%s") % (h64.encode_int24(self.rounds).decode("ascii"),
self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
@@ -335,8 +330,7 @@ class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
@classproperty
def _has_backend_os_crypt(cls):
- h = u('_/...lLDAxARksGCHin.')
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h)[1]==h)
+ return test_crypt("test", '_/...lLDAxARksGCHin.')
def _calc_checksum_builtin(self, secret):
if isinstance(secret, unicode):
@@ -344,8 +338,8 @@ class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
return raw_ext_crypt(secret, self.rounds, self.salt.encode("ascii")).decode("ascii")
def _calc_checksum_os_crypt(self, secret):
- ok, hash = safe_os_crypt(secret, self.to_string(native=False))
- if ok:
+ hash = safe_crypt(secret, self.to_string())
+ if hash:
return hash[9:]
else:
return self._calc_checksum_builtin(secret)
@@ -414,9 +408,9 @@ class bigcrypt(uh.HasSalt, uh.GenericHandler):
salt, chk = m.group("salt", "chk")
return cls(salt=salt, checksum=chk, strict=bool(chk))
- def to_string(self, native=True):
+ def to_string(self):
hash = u("%s%s") % (self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
@classmethod
def norm_checksum(cls, value, strict=False):
@@ -499,9 +493,9 @@ class crypt16(uh.HasSalt, uh.GenericHandler):
salt, chk = m.group("salt", "chk")
return cls(salt=salt, checksum=chk, strict=bool(chk))
- def to_string(self, native=True):
+ def to_string(self):
hash = u("%s%s") % (self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
diff --git a/passlib/handlers/md5_crypt.py b/passlib/handlers/md5_crypt.py
index 2dd9e7e..e24e66e 100644
--- a/passlib/handlers/md5_crypt.py
+++ b/passlib/handlers/md5_crypt.py
@@ -9,7 +9,7 @@ import logging; log = logging.getLogger(__name__)
from warnings import warn
#site
#libs
-from passlib.utils import classproperty, h64, safe_os_crypt
+from passlib.utils import classproperty, h64, safe_crypt, test_crypt
from passlib.utils.compat import b, bytes, irange, unicode, u
import passlib.utils.handlers as uh
#pkg
@@ -227,15 +227,14 @@ class md5_crypt(uh.HasManyBackends, _Md5Common):
@classproperty
def _has_backend_os_crypt(cls):
- h = u('$1$test$pi/xDtU5WFVRqYS6BMU8X/')
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h)[1]==h)
+ return test_crypt("test", '$1$test$pi/xDtU5WFVRqYS6BMU8X/')
def _calc_checksum_builtin(self, secret):
return raw_md5_crypt(secret, self.salt)
def _calc_checksum_os_crypt(self, secret):
- ok, hash = safe_os_crypt(secret, self.ident + self.salt)
- if ok:
+ hash = safe_crypt(secret, self.ident + self.salt)
+ if hash:
return hash[-22:]
else:
return self._calc_checksum_builtin(secret)
diff --git a/passlib/handlers/pbkdf2.py b/passlib/handlers/pbkdf2.py
index 748d75d..8621f03 100644
--- a/passlib/handlers/pbkdf2.py
+++ b/passlib/handlers/pbkdf2.py
@@ -11,7 +11,7 @@ from warnings import warn
#site
#libs
from passlib.utils import ab64_decode, ab64_encode
-from passlib.utils.compat import b, bytes, u, uascii_to_str, unicode
+from passlib.utils.compat import b, bytes, str_to_bascii, u, uascii_to_str, unicode
from passlib.utils.pbkdf2 import pbkdf2
import passlib.utils.handlers as uh
#pkg
@@ -313,14 +313,14 @@ class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
strict=bool(chk),
)
- def to_string(self, withchk=True, native=True):
+ def to_string(self, withchk=True):
if self.rounds == 400:
hash = u('$p5k2$$%s') % (self.salt,)
else:
hash = u('$p5k2$%x$%s') % (self.rounds, self.salt)
if withchk and self.checksum:
hash = u("%s$%s") % (hash,self.checksum)
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
@@ -328,7 +328,7 @@ class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
def calc_checksum(self, secret):
if isinstance(secret, unicode):
secret = secret.encode("utf-8")
- salt = self.to_string(withchk=False, native=False).encode("ascii")
+ salt = str_to_bascii(self.to_string(withchk=False))
result = pbkdf2(secret, salt, self.rounds, 24, "hmac-sha1")
return ab64_encode(result).decode("ascii")
diff --git a/passlib/handlers/sha1_crypt.py b/passlib/handlers/sha1_crypt.py
index c2eb41d..2a12345 100644
--- a/passlib/handlers/sha1_crypt.py
+++ b/passlib/handlers/sha1_crypt.py
@@ -13,7 +13,7 @@ import logging; log = logging.getLogger(__name__)
from warnings import warn
#site
#libs
-from passlib.utils import classproperty, h64, safe_os_crypt
+from passlib.utils import classproperty, h64, safe_crypt, test_crypt
from passlib.utils.compat import b, bytes, u, uascii_to_str, unicode
from passlib.utils.pbkdf2 import hmac_sha1
import passlib.utils.handlers as uh
@@ -90,11 +90,11 @@ class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
strict=bool(chk),
)
- def to_string(self, native=True):
+ def to_string(self):
hash = u("$sha1$%d$%s") % (self.rounds, self.salt)
if self.checksum:
hash += u("$") + self.checksum
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
@@ -105,8 +105,8 @@ class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
@classproperty
def _has_backend_os_crypt(cls):
- h = u('$sha1$1$Wq3GL2Vp$C8U25GvfHS8qGHimExLaiSFlGkAe')
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h)[1]==h)
+ return test_crypt("test", '$sha1$1$Wq3GL2Vp$C8U''25GvfHS8qGHim'
+ 'ExLaiSFlGkAe')
def _calc_checksum_builtin(self, secret):
if isinstance(secret, unicode):
@@ -132,8 +132,8 @@ class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler
]
def _calc_checksum_os_crypt(self, secret):
- ok, hash = safe_os_crypt(secret, self.to_string(native=False))
- if ok:
+ hash = safe_crypt(secret, self.to_string())
+ if hash:
return hash[hash.rindex("$")+1:]
else:
return self._calc_checksum_builtin(secret)
diff --git a/passlib/handlers/sha2_crypt.py b/passlib/handlers/sha2_crypt.py
index 8da3f1a..58f32a6 100644
--- a/passlib/handlers/sha2_crypt.py
+++ b/passlib/handlers/sha2_crypt.py
@@ -9,7 +9,7 @@ import logging; log = logging.getLogger(__name__)
from warnings import warn
#site
#libs
-from passlib.utils import classproperty, h64, safe_os_crypt
+from passlib.utils import classproperty, h64, safe_crypt, test_crypt
from passlib.utils.compat import b, bytes, belem_ord, irange, u, \
uascii_to_str, unicode
import passlib.utils.handlers as uh
@@ -314,12 +314,12 @@ class sha256_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl
strict=bool(chk),
)
- def to_string(self, native=True):
+ def to_string(self):
if self.rounds == 5000 and self.implicit_rounds:
hash = u("$5$%s$%s") % (self.salt, self.checksum or u(''))
else:
hash = u("$5$rounds=%d$%s$%s") % (self.rounds, self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
@@ -330,8 +330,8 @@ class sha256_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl
@classproperty
def _has_backend_os_crypt(cls):
- h = u("$5$rounds=1000$test$QmQADEXMG8POI5WDsaeho0P36yK3Tcrgboabng6bkb/")
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h)[1]==h)
+ return test_crypt("test", "$5$rounds=1000$test$QmQADEXMG8POI5W"
+ "Dsaeho0P36yK3Tcrgboabng6bkb/")
def _calc_checksum_builtin(self, secret):
if isinstance(secret, unicode):
@@ -346,12 +346,12 @@ class sha256_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl
return checksum.decode("ascii")
def _calc_checksum_os_crypt(self, secret):
- ok, result = safe_os_crypt(secret, self.to_string(native=False))
- if ok:
+ hash = safe_crypt(secret, self.to_string())
+ if hash:
#NOTE: avoiding full parsing routine via from_string().checksum,
# and just extracting the bit we need.
- assert result.startswith(u("$5$"))
- chk = result[-43:]
+ assert hash.startswith(u("$5$"))
+ chk = hash[-43:]
assert u('$') not in chk
return chk
else:
@@ -466,12 +466,12 @@ class sha512_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl
strict=bool(chk),
)
- def to_string(self, native=True):
+ def to_string(self):
if self.rounds == 5000 and self.implicit_rounds:
hash = u("$6$%s$%s") % (self.salt, self.checksum or u(''))
else:
hash = u("$6$rounds=%d$%s$%s") % (self.rounds, self.salt, self.checksum or u(''))
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#backend
@@ -482,8 +482,10 @@ class sha512_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl
@classproperty
def _has_backend_os_crypt(cls):
- h = u("$6$rounds=1000$test$2M/Lx6MtobqjLjobw0Wmo4Q5OFx5nVLJvmgseatA6oMnyWeBdRDx4DU.1H3eGmse6pgsOgDisWBGI5c7TZauS0")
- return bool(safe_os_crypt and safe_os_crypt(u("test"),h)[1]==h)
+ return test_crypt("test", "$6$rounds=1000$test$2M/Lx6Mtobqj"
+ "Ljobw0Wmo4Q5OFx5nVLJvmgseatA6oMn"
+ "yWeBdRDx4DU.1H3eGmse6pgsOgDisWBG"
+ "I5c7TZauS0")
#NOTE: testing w/ HashTimer shows 64-bit linux's crypt to be ~2.6x faster than builtin (627253 vs 238152 rounds/sec)
@@ -500,12 +502,12 @@ class sha512_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl
return checksum.decode("ascii")
def _calc_checksum_os_crypt(self, secret):
- ok, result = safe_os_crypt(secret, self.to_string(native=False))
- if ok:
+ hash = safe_crypt(secret, self.to_string())
+ if hash:
#NOTE: avoiding full parsing routine via from_string().checksum,
# and just extracting the bit we need.
- assert result.startswith(u("$6$"))
- chk = result[-86:]
+ assert hash.startswith(u("$6$"))
+ chk = hash[-86:]
assert u('$') not in chk
return chk
else:
diff --git a/passlib/handlers/sun_md5_crypt.py b/passlib/handlers/sun_md5_crypt.py
index c7b99bb..1a93c41 100644
--- a/passlib/handlers/sun_md5_crypt.py
+++ b/passlib/handlers/sun_md5_crypt.py
@@ -19,7 +19,7 @@ from warnings import warn
#libs
from passlib.utils import h64
from passlib.utils.compat import b, bytes, belem_ord, trange, u, \
- uascii_to_str, unicode
+ uascii_to_str, unicode, str_to_bascii
import passlib.utils.handlers as uh
#pkg
#local
@@ -307,7 +307,7 @@ class sun_md5_crypt(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
strict=bool(chk),
)
- def to_string(self, withchk=True, native=True):
+ def to_string(self, withchk=True):
ss = u('') if self.bare_salt else u('$')
rounds = self.rounds
if rounds > 0:
@@ -318,7 +318,7 @@ class sun_md5_crypt(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
chk = self.checksum
if chk:
hash = u("%s$%s") % (hash, chk)
- return uascii_to_str(hash) if native else hash
+ return uascii_to_str(hash)
#=========================================================
#primary interface
@@ -334,7 +334,7 @@ class sun_md5_crypt(uh.HasRounds, uh.HasSalt, uh.GenericHandler):
raise TypeError("no secret specified")
if isinstance(secret, unicode):
secret = secret.encode("utf-8")
- config = self.to_string(withchk=False,native=False).encode("ascii")
+ config = str_to_bascii(self.to_string(withchk=False))
return raw_sun_md5_crypt(secret, self.rounds, config).decode("ascii")
#=========================================================