diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-01-18 17:51:32 -0500 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-01-18 17:51:32 -0500 |
| commit | 666aa14bf15ed898472463d2ec890de0b8c60923 (patch) | |
| tree | f4ad79fb817cdca19e64dbb1abfe86c1a2c8ffc1 /passlib | |
| parent | b6d904be92c77bce061c78034145958401bba381 (diff) | |
| download | passlib-666aa14bf15ed898472463d2ec890de0b8c60923.tar.gz | |
import cleanups
* moved bytes compat functions from utils to utils.compat
(bord, bjoin, bjoin_ints, bjoin_elems, ujoin)
* renamed bord -> belem_ord for clarify
* a bunch of to_native_str() always use ascii, and
have fixed input types (always bytes or always unicode).
these don't need overhead of to_native_str(), so replaced
those calls with two new funcs: compat.bascii_to_str() /
compat.uascii_to_str()
* cleaned up a lot of imports from utils/utils.compat to
pull from correct module
* simplified the to_string() logic of a bunch of handlers
to reduce unicode<->byte transitions
Diffstat (limited to 'passlib')
35 files changed, 291 insertions, 279 deletions
diff --git a/passlib/apache.py b/passlib/apache.py index f34d1d0..ecde0ba 100644 --- a/passlib/apache.py +++ b/passlib/apache.py @@ -11,9 +11,8 @@ import sys #site #libs from passlib.context import CryptContext -from passlib.utils import render_bytes, bjoin, bytes, b, \ - to_unicode, to_bytes, consteq -from passlib.utils.compat import lmap, unicode, u +from passlib.utils import consteq, render_bytes +from passlib.utils.compat import b, bytes, bjoin, lmap, u, unicode #pkg #local __all__ = [ diff --git a/passlib/context.py b/passlib/context.py index 7b99a26..6466903 100644 --- a/passlib/context.py +++ b/passlib/context.py @@ -22,12 +22,11 @@ except ImportError: resource_string = None #libs from passlib.registry import get_crypt_handler, _validate_handler_name -from passlib.utils import to_bytes, to_unicode, bytes, \ - is_crypt_handler, rng, \ - PasslibPolicyWarning, tick, saslprep -from passlib.utils.compat import is_mapping, iteritems, num_types, \ - PY3, PY_MIN_32, unicode, bytes -from passlib.utils.compat.aliases import SafeConfigParser, StringIO, BytesIO +from passlib.utils import is_crypt_handler, rng, saslprep, tick, to_bytes, \ + to_unicode, PasslibPolicyWarning +from passlib.utils.compat import bytes, is_mapping, iteritems, num_types, \ + PY3, PY_MIN_32, unicode, SafeConfigParser, \ + StringIO, BytesIO #pkg #local __all__ = [ diff --git a/passlib/ext/django/models.py b/passlib/ext/django/models.py index b86a796..9ae17b7 100644 --- a/passlib/ext/django/models.py +++ b/passlib/ext/django/models.py @@ -15,8 +15,8 @@ see the Passlib documentation for details on how to use this app from django.conf import settings #pkg from passlib.context import CryptContext, CryptPolicy -from passlib.utils import is_crypt_context, bytes -from passlib.utils.compat import sb_types, unicode +from passlib.utils import is_crypt_context +from passlib.utils.compat import bytes, sb_types, unicode from passlib.ext.django.utils import DEFAULT_CTX, get_category, \ set_django_password_context diff --git a/passlib/ext/django/utils.py b/passlib/ext/django/utils.py index dbd3581..fc7c713 100644 --- a/passlib/ext/django/utils.py +++ b/passlib/ext/django/utils.py @@ -12,8 +12,8 @@ #site from warnings import warn #pkg -from passlib.utils import is_crypt_context, bytes -from passlib.utils.compat import get_method_function as um +from passlib.utils import is_crypt_context +from passlib.utils.compat import bytes, get_method_function as um #local __all__ = [ "get_category", diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py index f651dd0..8c1a1d8 100644 --- a/passlib/handlers/bcrypt.py +++ b/passlib/handlers/bcrypt.py @@ -16,7 +16,6 @@ import os import re import logging; log = logging.getLogger(__name__) from warnings import warn -from passlib.utils.compat import u #site try: from bcrypt import hashpw as pybcrypt_hashpw @@ -27,9 +26,9 @@ try: except ImportError: #pragma: no cover - though should run whole suite w/o bcryptor installed bcryptor_engine = None #libs -from passlib.utils import safe_os_crypt, classproperty, handlers as uh, \ - h64, to_native_str, rng, getrandstr, bytes, BCRYPT_CHARS as BCHARS -from passlib.utils.compat import unicode +from passlib.utils import safe_os_crypt, classproperty, rng, getrandstr +from passlib.utils.compat import bytes, u, uascii_to_str, unicode +import passlib.utils.handlers as uh #pkg #local @@ -145,7 +144,7 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. def to_string(self, native=True): hash = u("%s%02d$%s%s") % (self.ident, self.rounds, self.salt, self.checksum or u('')) - return to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash #========================================================= # specialized salt generation - fixes passlib issue 25 diff --git a/passlib/handlers/des_crypt.py b/passlib/handlers/des_crypt.py index 1669ac8..da64560 100644 --- a/passlib/handlers/des_crypt.py +++ b/passlib/handlers/des_crypt.py @@ -58,11 +58,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, classproperty, safe_os_crypt, b, bytes, \ - to_native_str, handlers as uh, bord -from passlib.utils.compat import unicode +from passlib.utils import classproperty, h64, h64big, safe_os_crypt +from passlib.utils.compat import b, bytes, belem_ord, u, uascii_to_str, unicode from passlib.utils.des import mdes_encrypt_int_block -from passlib.utils.compat import u +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -78,7 +77,7 @@ __all__ = [ def _crypt_secret_to_key(secret): "crypt helper which converts lower 7 bits of first 8 chars of secret -> 56-bit des key, padded to 64 bits" return sum( - (bord(c) & 0x7f) << (57-8*i) + (belem_ord(c) & 0x7f) << (57-8*i) for i, c in enumerate(secret[:8]) ) @@ -196,7 +195,7 @@ class des_crypt(uh.HasManyBackends, uh.HasSalt, uh.GenericHandler): def to_string(self, native=True): hash = u("%s%s") % (self.salt, self.checksum or u('')) - return to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash #========================================================= #backend @@ -325,7 +324,7 @@ class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler def to_string(self, native=True): hash = u("_%s%s%s") % (h64.encode_int24(self.rounds).decode("ascii"), self.salt, self.checksum or u('')) - return to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash #========================================================= #backend @@ -417,7 +416,7 @@ class bigcrypt(uh.HasSalt, uh.GenericHandler): def to_string(self, native=True): hash = u("%s%s") % (self.salt, self.checksum or u('')) - return to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash @classmethod def norm_checksum(cls, value, strict=False): @@ -502,7 +501,7 @@ class crypt16(uh.HasSalt, uh.GenericHandler): def to_string(self, native=True): hash = u("%s%s") % (self.salt, self.checksum or u('')) - return to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash #========================================================= #backend diff --git a/passlib/handlers/digests.py b/passlib/handlers/digests.py index e3c5a64..34e1dd3 100644 --- a/passlib/handlers/digests.py +++ b/passlib/handlers/digests.py @@ -9,8 +9,9 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import handlers as uh, to_native_str, bytes -from passlib.utils.compat import unicode +from passlib.utils import to_native_str +from passlib.utils.compat import bascii_to_str, bytes, unicode +import passlib.utils.handlers as uh from passlib.utils.md4 import md4 #pkg #local @@ -52,7 +53,7 @@ class HexDigestHash(uh.StaticHandler): raise TypeError("no secret provided") if isinstance(secret, unicode): secret = secret.encode("utf-8") - return to_native_str(cls._hash_func(secret).hexdigest()) + return bascii_to_str(cls._hash_func(secret).hexdigest()) @classmethod def _norm_hash(cls, hash): diff --git a/passlib/handlers/django.py b/passlib/handlers/django.py index e407814..2c4452b 100644 --- a/passlib/handlers/django.py +++ b/passlib/handlers/django.py @@ -9,8 +9,9 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, handlers as uh, b, bytes, to_unicode, to_native_str -from passlib.utils.compat import unicode, u +from passlib.utils import to_unicode +from passlib.utils.compat import b, bytes, uascii_to_str, unicode, u +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -65,8 +66,8 @@ class DjangoSaltedHash(uh.HasStubChecksum, uh.HasSalt, uh.GenericHandler): def to_string(self): chk = self.checksum or self._stub_checksum - out = u("%s%s$%s") % (self.ident, self.salt, chk) - return to_native_str(out) + hash = u("%s%s$%s") % (self.ident, self.salt, chk) + return uascii_to_str(hash) class django_salted_sha1(DjangoSaltedHash): """This class implements Django's Salted SHA1 hash, and follows the :ref:`password-hash-api`. @@ -210,7 +211,7 @@ class django_disabled(uh.StaticHandler): def genhash(cls, secret, config): if secret is None: raise TypeError("no secret provided") - return to_native_str(u("!")) + return "!" @classmethod def verify(cls, secret, hash): diff --git a/passlib/handlers/fshp.py b/passlib/handlers/fshp.py index 67c4ee1..424bf09 100644 --- a/passlib/handlers/fshp.py +++ b/passlib/handlers/fshp.py @@ -11,10 +11,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import handlers as uh, bytes, b, to_native_str -from passlib.utils.compat import iteritems, unicode +import passlib.utils.handlers as uh +from passlib.utils.compat import b, bytes, bascii_to_str, iteritems, u,\ + unicode from passlib.utils.pbkdf2 import pbkdf1 -from passlib.utils.compat import u #pkg #local __all__ = [ @@ -164,9 +164,8 @@ class fshp(uh.HasStubChecksum, uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, u def to_string(self): chk = self.checksum or self._stub_checksum salt = self.salt - data = b64encode(salt+chk).decode("ascii") - hash = u("{FSHP%d|%d|%d}%s") % (self.variant, len(salt), self.rounds, data) - return to_native_str(hash) + data = bascii_to_str(b64encode(salt+chk)) + return "{FSHP%d|%d|%d}%s" % (self.variant, len(salt), self.rounds, data) #========================================================= #backend diff --git a/passlib/handlers/ldap_digests.py b/passlib/handlers/ldap_digests.py index 2f6606d..8393be5 100644 --- a/passlib/handlers/ldap_digests.py +++ b/passlib/handlers/ldap_digests.py @@ -11,8 +11,9 @@ import re from warnings import warn #site #libs -from passlib.utils import handlers as uh, unix_crypt_schemes, b, bytes, to_native_str -from passlib.utils.compat import unicode, u +from passlib.utils import to_native_str, unix_crypt_schemes +from passlib.utils.compat import b, bytes, uascii_to_str, unicode, u +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -60,7 +61,7 @@ class _Base64DigestHelper(uh.StaticHandler): raise ValueError("not a %s hash" % (cls.name,)) chk = cls._hash_func(secret).digest() hash = cls.ident + b64encode(chk).decode("ascii") - return to_native_str(hash) + return uascii_to_str(hash) class _SaltedBase64DigestHelper(uh.HasStubChecksum, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler): "helper for ldap_salted_md5 / ldap_salted_sha1" @@ -93,7 +94,7 @@ class _SaltedBase64DigestHelper(uh.HasStubChecksum, uh.HasRawSalt, uh.HasRawChec def to_string(self): data = (self.checksum or self._stub_checksum) + self.salt hash = self.ident + b64encode(data).decode("ascii") - return to_native_str(hash) + return uascii_to_str(hash) def calc_checksum(self, secret): if secret is None: diff --git a/passlib/handlers/md5_crypt.py b/passlib/handlers/md5_crypt.py index 66641f7..2dd9e7e 100644 --- a/passlib/handlers/md5_crypt.py +++ b/passlib/handlers/md5_crypt.py @@ -9,9 +9,9 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import b, bytes, to_bytes, h64, safe_os_crypt, \ - classproperty, handlers as uh -from passlib.utils.compat import irange, unicode, u +from passlib.utils import classproperty, h64, safe_os_crypt +from passlib.utils.compat import b, bytes, irange, unicode, u +import passlib.utils.handlers as uh #pkg #local __all__ = [ diff --git a/passlib/handlers/misc.py b/passlib/handlers/misc.py index 948b851..7233768 100644 --- a/passlib/handlers/misc.py +++ b/passlib/handlers/misc.py @@ -8,7 +8,9 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import to_native_str, handlers as uh, bytes +from passlib.utils import to_native_str +from passlib.utils.compat import bytes, unicode +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -47,7 +49,8 @@ class unix_fallback(uh.StaticHandler): raise TypeError("secret must be string") if hash is None: raise ValueError("no hash provided") - return to_native_str(hash) + # NOTE: hash will generally be "!" + return to_native_str(hash, "ascii", errname="hash") @classmethod def verify(cls, secret, hash, enable_wildcard=False): diff --git a/passlib/handlers/mysql.py b/passlib/handlers/mysql.py index 9705b9d..f8d9cf1 100644 --- a/passlib/handlers/mysql.py +++ b/passlib/handlers/mysql.py @@ -30,8 +30,9 @@ from warnings import warn #site #libs #pkg -from passlib.utils import handlers as uh, to_native_str, b, bord, bytes -from passlib.utils.compat import unicode, u +from passlib.utils import to_native_str +from passlib.utils.compat import b, bytes, unicode, u, belem_ord +import passlib.utils.handlers as uh #local __all__ = [ 'mysql323', @@ -82,12 +83,11 @@ class mysql323(uh.StaticHandler): for c in secret: if c in b(' \t'): continue - tmp = bord(c) + tmp = belem_ord(c) nr1 ^= ((((nr1 & 63)+add)*tmp) + (nr1 << 8)) & MASK_32 nr2 = (nr2+((nr2 << 8) ^ nr1)) & MASK_32 add = (add+tmp) & MASK_32 - hash = u("%08x%08x") % (nr1 & MASK_31, nr2 & MASK_31) - return to_native_str(hash) + return "%08x%08x" % (nr1 & MASK_31, nr2 & MASK_31) @classmethod def _norm_hash(cls, hash): @@ -127,10 +127,11 @@ class mysql41(uh.StaticHandler): def genhash(cls, secret, config): if config is not None and not cls.identify(config): raise ValueError("not a mysql-4.1 hash") - #FIXME: no idea if mysql has a policy about handling unicode passwords + # FIXME: no idea if mysql has a policy about handling unicode passwords if isinstance(secret, unicode): secret = secret.encode("utf-8") - return '*' + sha1(sha1(secret).digest()).hexdigest().upper() + chk = bascii_to_str(sha1(sha1(secret).digest()).hexdigest()) + return '*' + chk.upper() @classmethod def _norm_hash(cls, hash): diff --git a/passlib/handlers/nthash.py b/passlib/handlers/nthash.py index 03340a9..1576a32 100644 --- a/passlib/handlers/nthash.py +++ b/passlib/handlers/nthash.py @@ -8,9 +8,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import handlers as uh, to_unicode, to_native_str, to_bytes, bytes +from passlib.utils import to_unicode +from passlib.utils.compat import bytes, u, uascii_to_str from passlib.utils.md4 import md4 -from passlib.utils.compat import u +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -69,7 +70,7 @@ class nthash(uh.HasStubChecksum, uh.HasManyIdents, uh.GenericHandler): def to_string(self): hash = self.ident + (self.checksum or self._stub_checksum) - return to_native_str(hash) + return uascii_to_str(hash) #========================================================= #primary interface @@ -86,7 +87,7 @@ class nthash(uh.HasStubChecksum, uh.HasManyIdents, uh.GenericHandler): returns string of raw bytes if ``hex=False``, returns digest as hexidecimal unicode if ``hex=True``. """ - secret = to_unicode(secret, "utf-8") + secret = to_unicode(secret, "utf-8", errname="secret") hash = md4(secret.encode("utf-16le")) if hex: return to_unicode(hash.hexdigest(), 'ascii') diff --git a/passlib/handlers/oracle.py b/passlib/handlers/oracle.py index f8fdc25..e0c6ff2 100644 --- a/passlib/handlers/oracle.py +++ b/passlib/handlers/oracle.py @@ -11,11 +11,11 @@ from warnings import warn #site #libs #pkg -from passlib.utils import xor_bytes, handlers as uh, bytes, to_unicode, \ - to_native_str, b -from passlib.utils.compat import irange, unicode +from passlib.utils import to_unicode, to_native_str, xor_bytes +from passlib.utils.compat import bytes, bascii_to_str, irange, u, \ + uascii_to_str, unicode from passlib.utils.des import des_encrypt_block -from passlib.utils.compat import u +import passlib.utils.handlers as uh #local __all__ = [ "oracle10g", @@ -104,18 +104,18 @@ class oracle10(uh.StaticHandler): # this whole mess really needs someone w/ an oracle system, # and some answers :) - def encode(value): + def encode(value, errname): "encode according to guess at how oracle encodes strings (see note above)" #we can't trust what original encoding was. #user should have passed us unicode in the first place. #but try decoding as utf-8 just to work for most common case. - value = to_unicode(value, "utf-8") + value = to_unicode(value, "utf-8", errname=errname) return value.upper().encode("utf-16-be") - input = encode(user) + encode(secret) + input = encode(user, 'user') + encode(secret, 'secret') hash = des_cbc_encrypt(ORACLE10_MAGIC, input) hash = des_cbc_encrypt(hash, input) - return to_native_str(hexlify(hash)).upper() + return bascii_to_str(hexlify(hash)).upper() @classmethod def _norm_hash(cls, hash): @@ -182,7 +182,7 @@ class oracle11(uh.HasStubChecksum, uh.HasSalt, uh.GenericHandler): def to_string(self): chk = (self.checksum or self._stub_checksum) hash = u("S:%s%s") % (chk.upper(), self.salt.upper()) - return to_native_str(hash) + return uascii_to_str(hash) def calc_checksum(self, secret): if isinstance(secret, unicode): diff --git a/passlib/handlers/pbkdf2.py b/passlib/handlers/pbkdf2.py index 889f511..748d75d 100644 --- a/passlib/handlers/pbkdf2.py +++ b/passlib/handlers/pbkdf2.py @@ -10,11 +10,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import ab64_encode, ab64_decode, \ - handlers as uh, to_native_str, to_unicode, bytes, b -from passlib.utils.compat import unicode +from passlib.utils import ab64_decode, ab64_encode +from passlib.utils.compat import b, bytes, u, uascii_to_str, unicode from passlib.utils.pbkdf2 import pbkdf2 -from passlib.utils.compat import u +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -88,7 +87,7 @@ class Pbkdf2DigestHandler(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gen hash = u('%s%d$%s$%s') % (self.ident, self.rounds, salt, chk) else: hash = u('%s%d$%s') % (self.ident, self.rounds, salt) - return to_native_str(hash) + return uascii_to_str(hash) def calc_checksum(self, secret): if isinstance(secret, unicode): @@ -222,12 +221,12 @@ class cta_pbkdf2_sha1(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Generic ) def to_string(self, withchk=True): - out = u('$p5k2$%x$%s') % (self.rounds, + hash = u('$p5k2$%x$%s') % (self.rounds, b64encode(self.salt, CTA_ALTCHARS).decode("ascii")) if withchk and self.checksum: - out = u("%s$%s") % (out, + hash = u("%s$%s") % (hash, b64encode(self.checksum, CTA_ALTCHARS).decode("ascii")) - return to_native_str(out) + return uascii_to_str(hash) #========================================================= #backend @@ -316,12 +315,12 @@ class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler): def to_string(self, withchk=True, native=True): if self.rounds == 400: - out = u('$p5k2$$%s') % (self.salt,) + hash = u('$p5k2$$%s') % (self.salt,) else: - out = u('$p5k2$%x$%s') % (self.rounds, self.salt) + hash = u('$p5k2$%x$%s') % (self.rounds, self.salt) if withchk and self.checksum: - out = u("%s$%s") % (out,self.checksum) - return to_native_str(out) if native else out + hash = u("%s$%s") % (hash,self.checksum) + return uascii_to_str(hash) if native else hash #========================================================= #backend @@ -379,7 +378,7 @@ class atlassian_pbkdf2_sha1(uh.HasStubChecksum, uh.HasRawSalt, uh.HasRawChecksum def to_string(self): data = self.salt + (self.checksum or self._stub_checksum) hash = self.ident + b64encode(data).decode("ascii") - return to_native_str(hash) + return uascii_to_str(hash) def calc_checksum(self, secret): #TODO: find out what crowd's policy is re: unicode @@ -453,7 +452,7 @@ class grub_pbkdf2_sha512(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gene hash = u('%s%d.%s.%s') % (self.ident, self.rounds, salt, chk) else: hash = u('%s%d.%s') % (self.ident, self.rounds, salt) - return to_native_str(hash) + return uascii_to_str(hash) def calc_checksum(self, secret): #TODO: find out what grub's policy is re: unicode diff --git a/passlib/handlers/phpass.py b/passlib/handlers/phpass.py index d83df21..bd72ef8 100644 --- a/passlib/handlers/phpass.py +++ b/passlib/handlers/phpass.py @@ -15,8 +15,9 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, handlers as uh, bytes, b, to_unicode, to_native_str -from passlib.utils.compat import unicode, u +from passlib.utils import h64 +from passlib.utils.compat import b, bytes, u, uascii_to_str, unicode +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -110,7 +111,7 @@ class phpass(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.GenericHandler): h64.encode_int6(self.rounds).decode("ascii"), self.salt, self.checksum or u('')) - return to_native_str(hash) + return uascii_to_str(hash) #========================================================= #backend diff --git a/passlib/handlers/postgres.py b/passlib/handlers/postgres.py index bb4c102..b12db22 100644 --- a/passlib/handlers/postgres.py +++ b/passlib/handlers/postgres.py @@ -10,8 +10,9 @@ from warnings import warn #site #libs #pkg -from passlib.utils import handlers as uh, to_unicode, to_native_str, bytes, b -from passlib.utils.compat import unicode, u +from passlib.utils import to_unicode +from passlib.utils.compat import b, bytes, bascii_to_str, unicode, u +import passlib.utils.handlers as uh #local __all__ = [ "postgres_md5", @@ -61,8 +62,7 @@ class postgres_md5(uh.StaticHandler): secret = secret.encode("utf-8") if isinstance(user, unicode): user = user.encode("utf-8") - hash = u("md5") + to_unicode(md5(secret + user).hexdigest()) - return to_native_str(hash) + return "md5" + bascii_to_str(md5(secret + user).hexdigest()) #========================================================= #eoc diff --git a/passlib/handlers/roundup.py b/passlib/handlers/roundup.py index 652d913..ac9a189 100644 --- a/passlib/handlers/roundup.py +++ b/passlib/handlers/roundup.py @@ -6,7 +6,7 @@ import logging; log = logging.getLogger(__name__) #site #libs -from passlib.utils import handlers as uh +import passlib.utils.handlers as uh from passlib.utils.compat import u #pkg #local diff --git a/passlib/handlers/scram.py b/passlib/handlers/scram.py index 26672c7..80031ed 100644 --- a/passlib/handlers/scram.py +++ b/passlib/handlers/scram.py @@ -23,11 +23,12 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import ab64_encode, ab64_decode, xor_bytes, \ - handlers as uh, to_native_str, to_unicode, consteq, saslprep -from passlib.utils.compat import unicode, bytes, u, b, iteritems, itervalues, \ - PY2, PY3 +from passlib.utils import ab64_decode, ab64_encode, consteq, saslprep, \ + to_native_str, xor_bytes +from passlib.utils.compat import b, bytes, bascii_to_str, iteritems, \ + itervalues, PY3, u, unicode from passlib.utils.pbkdf2 import pbkdf2, get_prf +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -317,7 +318,7 @@ class scram(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler): # parse hash if not hash: raise ValueError("no hash specified") - hash = to_native_str(hash, "ascii") + hash = to_native_str(hash, "ascii", errname="hash") if not hash.startswith("$scram$"): raise ValueError("invalid scram hash") parts = hash[7:].split("$") @@ -365,13 +366,11 @@ class scram(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler): ) def to_string(self, withchk=True): - salt = ab64_encode(self.salt) - if PY3: - salt = salt.decode("ascii") + salt = bascii_to_str(ab64_encode(self.salt)) chkmap = self.checksum if withchk and chkmap: chk_str = ",".join( - "%s=%s" % (alg, to_native_str(ab64_encode(chkmap[alg]))) + "%s=%s" % (alg, bascii_to_str(ab64_encode(chkmap[alg]))) for alg in self.algs ) else: diff --git a/passlib/handlers/sha1_crypt.py b/passlib/handlers/sha1_crypt.py index a23202e..c2eb41d 100644 --- a/passlib/handlers/sha1_crypt.py +++ b/passlib/handlers/sha1_crypt.py @@ -13,11 +13,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, handlers as uh, safe_os_crypt, classproperty, \ - to_native_str, to_unicode, bytes, b -from passlib.utils.compat import unicode +from passlib.utils import classproperty, h64, safe_os_crypt +from passlib.utils.compat import b, bytes, u, uascii_to_str, unicode from passlib.utils.pbkdf2 import hmac_sha1 -from passlib.utils.compat import u +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -92,10 +91,10 @@ class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler ) def to_string(self, native=True): - out = u("$sha1$%d$%s") % (self.rounds, self.salt) + hash = u("$sha1$%d$%s") % (self.rounds, self.salt) if self.checksum: - out += u("$") + self.checksum - return to_native_str(out) if native else out + hash += u("$") + self.checksum + return uascii_to_str(hash) if native else hash #========================================================= #backend diff --git a/passlib/handlers/sha2_crypt.py b/passlib/handlers/sha2_crypt.py index 7b00aad..8da3f1a 100644 --- a/passlib/handlers/sha2_crypt.py +++ b/passlib/handlers/sha2_crypt.py @@ -9,9 +9,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, safe_os_crypt, classproperty, handlers as uh, \ - to_native_str, to_unicode, bytes, b, bord -from passlib.utils.compat import unicode, u, irange +from passlib.utils import classproperty, h64, safe_os_crypt +from passlib.utils.compat import b, bytes, belem_ord, irange, u, \ + uascii_to_str, unicode +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -94,7 +95,7 @@ def raw_sha_crypt(secret, salt, rounds, hash): dp = extend(tmp.digest(), secret) #calc DS - hash of salt, extended to size of salt - tmp = hash(salt * (16+bord(a[0]))) + tmp = hash(salt * (16+belem_ord(a[0]))) ds = extend(tmp.digest(), salt) # @@ -318,7 +319,7 @@ class sha256_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl 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 to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash #========================================================= #backend @@ -470,7 +471,7 @@ class sha512_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl 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 to_native_str(hash) if native else hash + return uascii_to_str(hash) if native else hash #========================================================= #backend diff --git a/passlib/handlers/sun_md5_crypt.py b/passlib/handlers/sun_md5_crypt.py index 3bc5f0d..c7b99bb 100644 --- a/passlib/handlers/sun_md5_crypt.py +++ b/passlib/handlers/sun_md5_crypt.py @@ -17,8 +17,10 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, handlers as uh, to_native_str, to_unicode, bytes, b, bord -from passlib.utils.compat import trange, unicode, u +from passlib.utils import h64 +from passlib.utils.compat import b, bytes, belem_ord, trange, u, \ + uascii_to_str, unicode +import passlib.utils.handlers as uh #pkg #local __all__ = [ @@ -114,7 +116,7 @@ def raw_sun_md5_crypt(secret, rounds, salt): round = 0 while round < real_rounds: #convert last result byte string to list of byte-ints for easy access - rval = [ bord(c) for c in result ].__getitem__ + rval = [ belem_ord(c) for c in result ].__getitem__ #build up X bit by bit x = 0 @@ -309,14 +311,14 @@ class sun_md5_crypt(uh.HasRounds, uh.HasSalt, uh.GenericHandler): ss = u('') if self.bare_salt else u('$') rounds = self.rounds if rounds > 0: - out = u("$md5,rounds=%d$%s%s") % (rounds, self.salt, ss) + hash = u("$md5,rounds=%d$%s%s") % (rounds, self.salt, ss) else: - out = u("$md5$%s%s") % (self.salt, ss) + hash = u("$md5$%s%s") % (self.salt, ss) if withchk: chk = self.checksum if chk: - out = u("%s$%s") % (out, chk) - return to_native_str(out) if native else out + hash = u("%s$%s") % (hash, chk) + return uascii_to_str(hash) if native else hash #========================================================= #primary interface diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index bb2f78c..0e5d637 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -18,7 +18,7 @@ except ImportError: #pkg from passlib import hash from passlib.context import CryptContext, CryptPolicy, LazyCryptContext -from passlib.utils import to_bytes, to_unicode, PasslibPolicyWarning, tick +from passlib.utils import tick, to_bytes, to_unicode, PasslibPolicyWarning from passlib.utils.compat import irange, u import passlib.utils.handlers as uh from passlib.tests.utils import TestCase, mktemp, catch_warnings, \ diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index e04d65f..a4e021d 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -11,8 +11,8 @@ import warnings #site #pkg #module -from passlib.utils import bytes, b, to_native_str -from passlib.utils.compat import unicode, PY3, u +from passlib.utils.compat import b, bytes, bascii_to_str, irange, PY2, PY3, u, \ + unicode from passlib.tests.utils import TestCase, Params as ak, enable_option, catch_warnings def hb(source): @@ -387,30 +387,32 @@ class CodecTest(TestCase): "test to_native_str()" from passlib.utils import to_native_str - # ascii goes to native string w/o problems - self.assertEqual(to_native_str(u('abc')), 'abc') - self.assertEqual(to_native_str(b('abc')), 'abc') + # test plain ascii + self.assertEqual(to_native_str(u('abc', 'ascii')), 'abc') + self.assertEqual(to_native_str(b('abc', 'ascii')), 'abc') - # other types rejected - self.assertRaises(TypeError, to_native_str, None) - - # non-ascii unicode should throw error under py2, unless codec specified + # test invalid ascii if PY3: - self.assertEqual(to_native_str(u('\x00\xff')), '\x00\xff') + self.assertEqual(to_native_str(u('\xE0'), 'ascii'), '\xE0') + self.assertRaises(UnicodeDecodeError, to_native_str, b('\xC3\xA0'), + 'ascii') else: - self.assertEqual(to_native_str(u('\x00\xff')), '\x00\xc3\xbf') - self.assertRaises(UnicodeEncodeError, to_native_str, u('\x00\xff'), + self.assertRaises(UnicodeEncodeError, to_native_str, u('\xE0'), 'ascii') + self.assertEqual(to_native_str(b('\xC3\xA0'), 'ascii'), '\xC3\xA0') - # non-ascii bytes should throw error under py3, unless codec specified - if PY3: - self.assertRaises(UnicodeDecodeError, to_native_str, b('\x00\xff')) - else: - self.assertEqual(to_native_str(b('\x00\xff')), '\x00\xff') + # test latin-1 + self.assertEqual(to_native_str(u('\xE0'), 'latin-1'), '\xE0') + self.assertEqual(to_native_str(b('\xE0'), 'latin-1'), '\xE0') + + # test utf-8 + self.assertEqual(to_native_str(u('\xE0'), 'utf-8'), + '\xE0' if PY3 else '\xC3\xA0') + self.assertEqual(to_native_str(b('\xC3\xA0'), 'utf-8'), + '\xE0' if PY3 else '\xC3\xA0') - # latin-1 should work if explicitly chosen - self.assertEqual(to_native_str(u('\x00\xff'), 'latin-1'), '\x00\xff') - self.assertEqual(to_native_str(b('\x00\xff'), 'latin-1'), '\x00\xff') + # other types rejected + self.assertRaises(TypeError, to_native_str, None, 'ascii') def test_is_ascii_safe(self): "test is_ascii_safe()" @@ -894,7 +896,7 @@ class _MD4_Test(TestCase): "test md4 digest()" md4 = self.hash for input, hex in self.vectors: - out = to_native_str(hexlify(md4(input).digest())) + out = bascii_to_str(hexlify(md4(input).digest())) self.assertEqual(out, hex) def test_md4_copy(self): diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index 838d016..9028df4 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -13,9 +13,9 @@ import warnings from passlib.hash import ldap_md5, sha256_crypt from passlib.registry import _unload_handler_name as unload_handler_name, \ register_crypt_handler, get_crypt_handler -from passlib.utils import rng, getrandstr, handlers as uh, bytes, b, \ - to_native_str, to_unicode, MissingBackendError, JYTHON -from passlib.utils.compat import unicode +from passlib.utils import getrandstr, JYTHON, rng, to_unicode, MissingBackendError +from passlib.utils.compat import b, bytes, bascii_to_str, uascii_to_str, unicode +import passlib.utils.handlers as uh from passlib.tests.utils import HandlerCase, TestCase, catch_warnings, \ dummy_handler_in_registry from passlib.utils.compat import u @@ -44,7 +44,7 @@ class SkeletonTest(TestCase): hash = hash.decode("ascii") if hash not in (u('a'),u('b')): raise ValueError - return to_native_str(u('b') if flag else u('a')) + return 'b' if flag else 'a' #check default identify method self.assertTrue(d1.identify(u('a'))) @@ -58,7 +58,7 @@ class SkeletonTest(TestCase): #check default genconfig method self.assertIs(d1.genconfig(), None) d1._stub_config = u('b') - self.assertEqual(d1.genconfig(), to_native_str('b')) + self.assertEqual(d1.genconfig(), 'b') #check default verify method self.assertTrue(d1.verify('s','a')) @@ -69,9 +69,9 @@ class SkeletonTest(TestCase): self.assertRaises(ValueError, d1.verify, 's', 'c') #check default encrypt method - self.assertEqual(d1.encrypt('s'), to_native_str('a')) - self.assertEqual(d1.encrypt('s'), to_native_str('a')) - self.assertEqual(d1.encrypt('s', flag=True), to_native_str('b')) + self.assertEqual(d1.encrypt('s'), 'a') + self.assertEqual(d1.encrypt('s'), 'a') + self.assertEqual(d1.encrypt('s', flag=True), 'b') #========================================================= #GenericHandler & mixins @@ -411,7 +411,7 @@ class UnsaltedHash(uh.StaticHandler): if isinstance(secret, unicode): secret = secret.encode("utf-8") data = b("boblious") + secret - return to_native_str(hashlib.sha1(data).hexdigest()) + return bascii_to_str(hashlib.sha1(data).hexdigest()) class SaltedHash(uh.HasSalt, uh.GenericHandler): "test algorithm with a salt" @@ -439,13 +439,13 @@ class SaltedHash(uh.HasSalt, uh.GenericHandler): def to_string(self): hash = u("@salt%s%s") % (self.salt, self.checksum or self._stub_checksum) - return to_native_str(hash) + return uascii_to_str(hash) def calc_checksum(self, secret): if isinstance(secret, unicode): secret = secret.encode("utf-8") data = self.salt.encode("ascii") + secret + self.salt.encode("ascii") - return to_unicode(hashlib.sha1(data).hexdigest(), "latin-1") + return hashlib.sha1(data).hexdigest().decode("ascii") #========================================================= #test sample algorithms - really a self-test of HandlerCase diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index c9a5aff..85c9ea0 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -10,7 +10,7 @@ import re import os import sys import tempfile -from passlib.utils.compat import u, PY27, PY_MIN_32, PY3 +from passlib.utils.compat import PY27, PY_MIN_32, PY3 try: import unittest2 as unittest @@ -30,12 +30,12 @@ if ut_version < 2: #used to provide replacement skipTest() method from nose.plugins.skip import SkipTest #pkg -from passlib import registry, utils -from passlib.utils import classproperty, handlers as uh, \ - has_rounds_info, has_salt_info, MissingBackendError, \ - rounds_cost_values, b, bytes -from passlib.utils.compat import iteritems, irange, callable, sb_types, \ - exc_err, unicode +import passlib.registry as registry +from passlib.utils import has_rounds_info, has_salt_info, MissingBackendError,\ + rounds_cost_values, classproperty +from passlib.utils.compat import b, bytes, iteritems, irange, callable, \ + sb_types, exc_err, u, unicode +import passlib.utils.handlers as uh #local __all__ = [ #util funcs @@ -542,7 +542,8 @@ class HandlerCase(TestCase): #this allows use to test as much of the hash's code path #as possible, even if current OS doesn't provide crypt() support #for the hash. - self._orig_os_crypt = utils.os_crypt + import passlib.utils as mod + self._orig_os_crypt = mod.os_crypt def crypt_stub(secret, hash): tmp = h.get_backend() try: @@ -553,12 +554,13 @@ class HandlerCase(TestCase): if not PY3 and isinstance(hash, unicode): hash = hash.encode("ascii") return hash - utils.os_crypt = crypt_stub + mod.os_crypt = crypt_stub h.set_backend(backend) def tearDown(self): if self._orig_os_crypt: - utils.os_crypt = self._orig_os_crypt + import passlib.utils as mod + mod.os_crypt = self._orig_os_crypt if self._orig_backend: self.handler.set_backend(self._orig_backend) @@ -1006,7 +1008,8 @@ class HandlerCase(TestCase): possible = True if handler.has_backend("os_crypt"): def check_crypt(secret, hash): - self.assertEqual(utils.os_crypt(secret, hash), hash, + from passlib.utils import os_crypt + self.assertEqual(os_crypt(secret, hash), hash, "os_crypt(%r,%r):" % (secret, hash)) helpers.append(check_crypt) @@ -1076,7 +1079,8 @@ def _enable_backend_case(handler, backend): if enable_option("all-backends") or _is_default_backend(handler, backend): if handler.has_backend(backend): return True, None - if backend == "os_crypt" and utils.safe_os_crypt: + from passlib.utils import has_os_crypt + if backend == "os_crypt" and has_os_crypt: if enable_option("cover") and _has_other_backends(handler, "os_crypt"): #in this case, HandlerCase will monkeypatch os_crypt #to use another backend, just so we can test os_crypt fully. diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index 0f53a09..74d53c2 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -17,7 +17,9 @@ import unicodedata from warnings import warn #site #pkg -from passlib.utils.compat import irange, PY3, unicode, bytes, u, b, _add_doc +from passlib.utils.compat import _add_doc, b, bytes, bjoin, bjoin_ints, \ + bjoin_elems, exc_err, irange, imap, PY3, u, \ + ujoin, unicode #local __all__ = [ # constants @@ -33,9 +35,6 @@ __all__ = [ ## "relocated_function", ## "memoized_class_property", - #byte compat aliases - 'bytes', - # unicode helpers 'consteq', 'saslprep', @@ -245,7 +244,6 @@ def relocated_function(target, msg=None, name=None, deprecated=None, mod=None, #============================================================================= # unicode helpers #============================================================================= -ujoin = _UEMPTY.join def consteq(left, right): """check two strings/bytes for equality, taking constant time relative @@ -431,67 +429,9 @@ def saslprep(source, errname="value"): return data -#========================================================== +#============================================================================= # bytes helpers -#========================================================== - -#helpers for joining / extracting elements -bjoin = _BEMPTY.join - -#def bjoin_elems(elems): -# """takes series of bytes elements, returns bytes. -# -# elem should be result of bytes[x]. -# this is another bytes instance under py2, -# but it int under py3. -# -# returns bytes. -# -# this is bytes() constructor under py3, -# but b"".join() under py2. -# """ -# if PY3: -# return bytes(elems) -# else: -# return bjoin(elems) -# -#for efficiency, don't bother with above wrapper... -if PY3: - bjoin_elems = bytes -else: - bjoin_elems = bjoin - -#def bord(elem): -# """takes bytes element, returns integer. -# -# elem should be result of bytes[x]. -# this is another bytes instance under py2, -# but it int under py3. -# -# returns int in range(0,256). -# -# this is ord() under py2, and noop under py3. -# """ -# if PY3: -# assert isinstance(elem, int) -# return elem -# else: -# assert isinstance(elem, bytes) -# return ord(elem) -# -#for efficiency, don't bother with above wrapper... -if PY3: - def bord(elem): - return elem -else: - bord = ord - -if PY3: - bjoin_ints = bytes -else: - def bjoin_ints(values): - return bjoin(chr(v) for v in values) - +#============================================================================= if PY3: def xor_bytes(left, right): return bytes(l ^ r for l, r in zip(left, right)) @@ -525,9 +465,10 @@ def render_bytes(source, *args): @deprecated_function(deprecated="1.6", removed="1.8") def bytes_to_int(value): "decode string of bytes as single big-endian integer" + from passlib.utils.compat import belem_ord out = 0 for v in value: - out = (out<<8) | bord(v) + out = (out<<8) | belem_ord(v) return out @deprecated_function(deprecated="1.6", removed="1.8") diff --git a/passlib/utils/_blowfish/__init__.py b/passlib/utils/_blowfish/__init__.py index 41914dd..407b78f 100644 --- a/passlib/utils/_blowfish/__init__.py +++ b/passlib/utils/_blowfish/__init__.py @@ -54,9 +54,8 @@ released under the BSD license:: from itertools import chain import struct #pkg -from passlib.utils import Base64Engine, BCRYPT_CHARS, rng, getrandbytes, bytes, bord -from passlib.utils.compat import b, unicode, u -from passlib.utils.compat.aliases import BytesIO +from passlib.utils import Base64Engine, BCRYPT_CHARS, getrandbytes, rng +from passlib.utils.compat import b, bytes, BytesIO, unicode, u from passlib.utils._blowfish.unrolled import BlowfishEngine #local __all__ = [ diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py index 5b7750c..26892ea 100644 --- a/passlib/utils/compat.py +++ b/passlib/utils/compat.py @@ -12,19 +12,46 @@ PY_MIN_32 = sys.version_info >= (3,2) # py 3.2 or later #============================================================================= # common imports #============================================================================= +import logging; log = logging.getLogger(__name__) if PY3: import builtins else: import __builtin__ as builtins + +def _add_doc(obj, doc): + """add docstring to an object""" + obj.__doc__ = doc + #============================================================================= # the default exported vars #============================================================================= __all__ = [ - "u", "b", - "irange", "srange", ##"lrange", - "lmap", - "iteritems", + # python versions + 'PY2', 'PY3', 'PY_MAX_25', 'PY27', 'PY_MIN_32', + + # io + 'print_', + + # type detection + 'is_mapping', + 'callable', + 'int_types', + 'num_types', + + # unicode/bytes types & helpers + 'u', 'b', + 'unicode', 'bytes', 'sb_types', + 'uascii_to_str', 'bascii_to_str', + 'ujoin', 'bjoin', 'bjoin_ints', 'bjoin_elems', 'belem_ord', + + # iteration helpers + 'irange', 'trange', #'lrange', + 'imap', 'lmap', + 'iteritems', 'itervalues', + + # introspection + 'exc_err', 'get_method_function', '_add_doc', ] #============================================================================= @@ -85,7 +112,6 @@ if (3,0) <= sys.version_info < (3,2): from collections import Callable def callable(obj): return isinstance(obj, Callable) - __all__.append("callable") else: callable = builtins.callable @@ -97,36 +123,81 @@ else: num_types = (int, long, float) #============================================================================= -# unicode / bytes helpers +# unicode & bytes types #============================================================================= if PY3: + unicode = str + bytes = builtins.bytes +# string_types = (unicode,) + def u(s): + assert isinstance(s, str) return s + def b(s): assert isinstance(s, str) return s.encode("latin-1") - unicode = str - bytes = builtins.bytes - __all__.append("unicode") -# string_types = (unicode,) else: def u(s): + assert isinstance(s, str) return s.decode("unicode_escape") + def b(s): assert isinstance(s, str) return s - if PY_MAX_25: - bytes = str - __all__.append("bytes") - else: - bytes = builtins.bytes - unicode = builtins.unicode -# string_types = (unicode, bytes) sb_types = (unicode, bytes) -# bytes format +#============================================================================= +# unicode & bytes helpers +#============================================================================= +# function to join list of unicode strings +ujoin = u('').join + +# function to join list of byte strings +bjoin = b('').join + +if PY3: + def uascii_to_str(s): + assert isinstance(s, unicode) + return s + + def bascii_to_str(s): + assert isinstance(s, bytes) + return s.decode("ascii") + + bjoin_ints = bjoin_elems = bytes + + def belem_ord(elem): + return elem + +else: + def uascii_to_str(s): + assert isinstance(s, unicode) + return s.encode("ascii") + + def bascii_to_str(s): + assert isinstance(s, bytes) + return s + + def bjoin_ints(values): + return bjoin(chr(v) for v in values) + + bjoin_elems = bjoin + + belem_ord = ord + +_add_doc(uascii_to_str, "helper to convert ascii unicode -> native str") +_add_doc(bascii_to_str, "helper to convert ascii bytes -> native str") + +# bjoin_ints -- function to convert list of ordinal integers to byte string. + +# bjoin_elems -- function to convert list of byte elements to byte string; +# i.e. what's returned by ``b('a')[0]``... +# this is b('a') under PY2, but 97 under PY3. + +# belem_ord -- function to convert byte element to integer -- a noop under PY3 #============================================================================= # iteration helpers @@ -144,7 +215,7 @@ if PY3: def lmap(*a, **k): return list(map(*a,**k)) - # imap = map + imap = map else: irange = xrange @@ -152,7 +223,7 @@ else: ##lrange = range lmap = map - # from itertools import imap + from itertools import imap if PY3: def iteritems(d): @@ -179,10 +250,6 @@ else: def get_method_function(method): return method.im_func -def _add_doc(obj, doc): - """add docstring to an object""" - obj.__doc__ = doc - #============================================================================= # input/output #============================================================================= diff --git a/passlib/utils/des.py b/passlib/utils/des.py index ea01048..67c6d93 100644 --- a/passlib/utils/des.py +++ b/passlib/utils/des.py @@ -45,8 +45,7 @@ which has some nice notes on how this all works - # core import struct # pkg -from passlib.utils import bytes, bord, bjoin_ints -from passlib.utils.compat import trange, irange +from passlib.utils.compat import bytes, bjoin_ints, belem_ord, irange, trange # local __all__ = [ "expand_des_key", @@ -589,7 +588,7 @@ def expand_des_key(key): def iter_bits(source): for c in source: - v = bord(c) + v = belem_ord(c) for i in irange(7,-1,-1): yield (v>>i) & 1 diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py index 52ab2cc..7643c01 100644 --- a/passlib/utils/handlers.py +++ b/passlib/utils/handlers.py @@ -14,11 +14,11 @@ from warnings import warn #site #libs from passlib.registry import get_crypt_handler -from passlib.utils import to_native_str, bytes, b, consteq, \ - classproperty, h64, getrandstr, getrandbytes, bjoin_ints, \ - rng, is_crypt_handler, ALL_BYTE_VALUES, MissingBackendError, \ - BASE64_CHARS, HASH64_CHARS -from passlib.utils.compat import unicode, u, irange +from passlib.utils import is_crypt_handler +from passlib.utils import classproperty, consteq, getrandstr, getrandbytes,\ + BASE64_CHARS, HASH64_CHARS, rng, to_native_str, MissingBackendError +from passlib.utils.compat import b, bjoin_ints, bytes, irange, u, \ + uascii_to_str, unicode #pkg #local __all__ = [ @@ -136,7 +136,7 @@ def render_mc2(ident, salt, checksum, sep=u("$")): hash = u("%s%s%s%s") % (ident, salt, sep, checksum) else: hash = u("%s%s") % (ident, salt) - return to_native_str(hash) + return uascii_to_str(hash) def render_mc3(ident, rounds, salt, checksum, sep=u("$")): "format hash using 3-part modular crypt format; inverse of parse_mc3" @@ -144,7 +144,7 @@ def render_mc3(ident, rounds, salt, checksum, sep=u("$")): hash = u("%s%s%s%s%s%s") % (ident, rounds, sep, salt, sep, checksum) else: hash = u("%s%s%s%s") % (ident, rounds, sep, salt) - return to_native_str(hash) + return uascii_to_str(hash) #===================================================== #StaticHandler @@ -1335,7 +1335,7 @@ class PrefixWrapper(object): if not hash.startswith(orig_prefix): raise ValueError("not a valid %s hash" % (self.wrapped.name,)) wrapped = self.prefix + hash[len(orig_prefix):] - return to_native_str(wrapped) + return uascii_to_str(wrapped) def identify(self, hash): if not hash: diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py index df3be70..a63ad11 100644 --- a/passlib/utils/md4.py +++ b/passlib/utils/md4.py @@ -15,8 +15,7 @@ from binascii import hexlify import struct from warnings import warn #site -from passlib.utils import b, bytes, to_native_str -from passlib.utils.compat import irange, PY3 +from passlib.utils.compat import b, bytes, bascii_to_str, irange, PY3 #local __all__ = [ "md4" ] #========================================================================= @@ -224,8 +223,7 @@ class md4(object): return out def hexdigest(self): - # PY3: hexlify returns bytes, but hexdigest should return str. - return to_native_str(hexlify(self.digest())) + return bascii_to_str(hexlify(self.digest())) #========================================================================= #eoc diff --git a/passlib/utils/pbkdf2.py b/passlib/utils/pbkdf2.py index c48f751..c880457 100644 --- a/passlib/utils/pbkdf2.py +++ b/passlib/utils/pbkdf2.py @@ -20,9 +20,8 @@ try: except ImportError: _EVP = None #pkg -from passlib.utils import xor_bytes, to_bytes, b, bytes -from passlib.utils.compat import irange, callable, int_types -from passlib.utils.compat.aliases import BytesIO +from passlib.utils import to_bytes, xor_bytes +from passlib.utils.compat import b, bytes, BytesIO, irange, callable, int_types #local __all__ = [ "hmac_sha1", diff --git a/passlib/win32.py b/passlib/win32.py index 19b3ced..a572f9a 100644 --- a/passlib/win32.py +++ b/passlib/win32.py @@ -27,8 +27,7 @@ See also :mod:`passlib.hash.nthash`. from binascii import hexlify #site #pkg -from passlib.utils import b -from passlib.utils.compat import unicode +from passlib.utils.compat import b, unicode from passlib.utils.des import des_encrypt_block from passlib.hash import nthash #local |
