예제 #1
0
def update_settings(**kwds):
    """helper to update django settings from kwds"""
    for k,v in iteritems(kwds):
        if v is UNSET:
            if hasattr(settings, k):
                delattr(settings, k)
        else:
            setattr(settings, k, v)
예제 #2
0
def update_settings(**kwds):
    """helper to update django settings from kwds"""
    for k, v in iteritems(kwds):
        if v is UNSET:
            if hasattr(settings, k):
                delattr(settings, k)
        else:
            setattr(settings, k, v)
예제 #3
0
 def check_all(self, strict=False):
     """run sanity check on all keys, issue warning if out of sync"""
     same = self._is_same_value
     for path, (orig, expected) in iteritems(self._state):
         if same(self._get_path(path), expected):
             continue
         msg = "another library has patched resource: %r" % path
         if strict:
             raise RuntimeError(msg)
         else:
             warn(msg, PasslibRuntimeWarning)
예제 #4
0
 def safe_summary(self, encoded):
     from django.contrib.auth.hashers import mask_hash, _, SortedDict
     handler = self.passlib_handler
     items = [
         # since this is user-facing, we're reporting passlib's name,
         # without the distracting PASSLIB_HASHER_PREFIX prepended.
         (_('algorithm'), handler.name),
     ]
     if hasattr(handler, "parsehash"):
         kwds = handler.parsehash(encoded, sanitize=mask_hash)
         for key, value in iteritems(kwds):
             key = self._translate_kwds.get(key, key)
             items.append((_(key), value))
     return SortedDict(items)
예제 #5
0
 def safe_summary(self, encoded):
     from django.contrib.auth.hashers import mask_hash, _, SortedDict
     handler = self.passlib_handler
     items = [
         # since this is user-facing, we're reporting passlib's name,
         # without the distracting PASSLIB_HASHER_PREFIX prepended.
         (_('algorithm'), handler.name),
     ]
     if hasattr(handler, "parsehash"):
         kwds = handler.parsehash(encoded, sanitize=mask_hash)
         for key, value in iteritems(kwds):
             key = self._translate_kwds.get(key, key)
             items.append((_(key), value))
     return SortedDict(items)
예제 #6
0
 def _norm_checksum(self, checksum):
     if checksum is None:
         return None
     for alg, digest in iteritems(checksum):
         if alg != norm_hash_name(alg, "iana"):
             raise ValueError("malformed algorithm name in scram hash: %r" % (alg,))
         if len(alg) > 9:
             raise ValueError("SCRAM limits algorithm names to " "9 characters: %r" % (alg,))
         if not isinstance(digest, bytes):
             raise uh.exc.ExpectedTypeError(digest, "raw bytes", "digests")
         # TODO: verify digest size (if digest is known)
     if "sha-1" not in checksum:
         # NOTE: required because of SCRAM spec.
         raise ValueError("sha-1 must be in algorithm list of scram hash")
     return checksum
예제 #7
0
 def _norm_checksum(self, checksum, relaxed=False):
     if not isinstance(checksum, dict):
         raise uh.exc.ExpectedTypeError(checksum, "dict", "checksum")
     for alg, digest in iteritems(checksum):
         if alg != norm_hash_name(alg, 'iana'):
             raise ValueError("malformed algorithm name in scram hash: %r" %
                              (alg,))
         if len(alg) > 9:
             raise ValueError("SCRAM limits algorithm names to "
                              "9 characters: %r" % (alg,))
         if not isinstance(digest, bytes):
             raise uh.exc.ExpectedTypeError(digest, "raw bytes", "digests")
         # TODO: verify digest size (if digest is known)
     if 'sha-1' not in checksum:
         # NOTE: required because of SCRAM spec.
         raise ValueError("sha-1 must be in algorithm list of scram hash")
     return checksum
예제 #8
0
    def verify(cls, secret, hash, full=False):
        uh.validate_secret(secret)
        self = cls.from_string(hash)
        chkmap = self.checksum
        if not chkmap:
            raise ValueError("expected %s hash, got %s config string instead" %
                             (cls.name, cls.name))

        # NOTE: to make the verify method efficient, we just calculate hash
        # of shortest digest by default. apps can pass in "full=True" to
        # check entire hash for consistency.
        if full:
            correct = failed = False
            for alg, digest in iteritems(chkmap):
                other = self._calc_checksum(secret, alg)
                # NOTE: could do this length check in norm_algs(),
                # but don't need to be that strict, and want to be able
                # to parse hashes containing algs not supported by platform.
                # it's fine if we fail here though.
                if len(digest) != len(other):
                    raise ValueError(
                        "mis-sized %s digest in scram hash: %r != %r" %
                        (alg, len(digest), len(other)))
                if consteq(other, digest):
                    correct = True
                else:
                    failed = True
            if correct and failed:
                raise ValueError("scram hash verified inconsistently, "
                                 "may be corrupted")
            else:
                return correct
        else:
            # XXX: should this just always use sha1 hash? would be faster.
            # otherwise only verify against one hash, pick one w/ best security.
            for alg in self._verify_algs:
                if alg in chkmap:
                    other = self._calc_checksum(secret, alg)
                    return consteq(other, chkmap[alg])
            # there should always be sha-1 at the very least,
            # or something went wrong inside _norm_algs()
            raise AssertionError("sha-1 digest not found!")
예제 #9
0
파일: scram.py 프로젝트: cutso/passlib
    def verify(cls, secret, hash, full=False):
        uh.validate_secret(secret)
        self = cls.from_string(hash)
        chkmap = self.checksum
        if not chkmap:
            raise ValueError("expected %s hash, got %s config string instead" %
                             (cls.name, cls.name))

        # NOTE: to make the verify method efficient, we just calculate hash
        # of shortest digest by default. apps can pass in "full=True" to
        # check entire hash for consistency.
        if full:
            correct = failed = False
            for alg, digest in iteritems(chkmap):
                other = self._calc_checksum(secret, alg)
                # NOTE: could do this length check in norm_algs(),
                # but don't need to be that strict, and want to be able
                # to parse hashes containing algs not supported by platform.
                # it's fine if we fail here though.
                if len(digest) != len(other):
                    raise ValueError("mis-sized %s digest in scram hash: %r != %r"
                                     % (alg, len(digest), len(other)))
                if consteq(other, digest):
                    correct = True
                else:
                    failed = True
            if correct and failed:
                raise ValueError("scram hash verified inconsistently, "
                                 "may be corrupted")
            else:
                return correct
        else:
            # XXX: should this just always use sha1 hash? would be faster.
            # otherwise only verify against one hash, pick one w/ best security.
            for alg in self._verify_algs:
                if alg in chkmap:
                    other = self._calc_checksum(secret, alg)
                    return consteq(other, chkmap[alg])
            # there should always be sha-1 at the very least,
            # or something went wrong inside _norm_algs()
            raise AssertionError("sha-1 digest not found!")
예제 #10
0
 def _iter_lines(self):
     "iterator yielding lines of database"
     return (self._render_record(key,value) for key,value in iteritems(self._records))
예제 #11
0
파일: fshp.py 프로젝트: Baristi000/new_api
class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
    """This class implements the FSHP password hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and a variable number of rounds.

    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:

    :param salt:
        Optional raw salt string.
        If not specified, one will be autogenerated (this is recommended).

    :param salt_size:
        Optional number of bytes to use when autogenerating new salts.
        Defaults to 16 bytes, but can be any non-negative value.

    :param rounds:
        Optional number of rounds to use.
        Defaults to 480000, must be between 1 and 4294967295, inclusive.

    :param variant:
        Optionally specifies variant of FSHP to use.

        * ``0`` - uses SHA-1 digest (deprecated).
        * ``1`` - uses SHA-2/256 digest (default).
        * ``2`` - uses SHA-2/384 digest.
        * ``3`` - uses SHA-2/512 digest.

    :type relaxed: bool
    :param relaxed:
        By default, providing an invalid value for one of the other
        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
        will be issued instead. Correctable errors include ``rounds``
        that are too small or too large, and ``salt`` strings that are too long.

        .. versionadded:: 1.6
    """

    #===================================================================
    # class attrs
    #===================================================================
    #--GenericHandler--
    name = "fshp"
    setting_kwds = ("salt", "salt_size", "rounds", "variant")
    checksum_chars = uh.PADDED_BASE64_CHARS
    ident = u("{FSHP")
    # checksum_size is property() that depends on variant

    #--HasRawSalt--
    default_salt_size = 16 # current passlib default, FSHP uses 8
    max_salt_size = None

    #--HasRounds--
    # FIXME: should probably use different default rounds
    # based on the variant. setting for default variant (sha256) for now.
    default_rounds = 480000 # current passlib default, FSHP uses 4096
    min_rounds = 1 # set by FSHP
    max_rounds = 4294967295 # 32-bit integer limit - not set by FSHP
    rounds_cost = "linear"

    #--variants--
    default_variant = 1
    _variant_info = {
        # variant: (hash name, digest size)
        0: ("sha1",     20),
        1: ("sha256",   32),
        2: ("sha384",   48),
        3: ("sha512",   64),
        }
    _variant_aliases = dict(
        [(unicode(k),k) for k in _variant_info] +
        [(v[0],k) for k,v in iteritems(_variant_info)]
        )

    #===================================================================
    # configuration
    #===================================================================
    @classmethod
    def using(cls, variant=None, **kwds):
        subcls = super(fshp, cls).using(**kwds)
        if variant is not None:
            subcls.default_variant = cls._norm_variant(variant)
        return subcls

    #===================================================================
    # instance attrs
    #===================================================================
    variant = None

    #===================================================================
    # init
    #===================================================================
    def __init__(self, variant=None, **kwds):
        # NOTE: variant must be set first, since it controls checksum size, etc.
        self.use_defaults = kwds.get("use_defaults") # load this early
        if variant is not None:
            variant = self._norm_variant(variant)
        elif self.use_defaults:
            variant = self.default_variant
            assert self._norm_variant(variant) == variant, "invalid default variant: %r" % (variant,)
        else:
            raise TypeError("no variant specified")
        self.variant = variant
        super(fshp, self).__init__(**kwds)

    @classmethod
    def _norm_variant(cls, variant):
        if isinstance(variant, bytes):
            variant = variant.decode("ascii")
        if isinstance(variant, unicode):
            try:
                variant = cls._variant_aliases[variant]
            except KeyError:
                raise ValueError("invalid fshp variant")
        if not isinstance(variant, int):
            raise TypeError("fshp variant must be int or known alias")
        if variant not in cls._variant_info:
            raise ValueError("invalid fshp variant")
        return variant

    @property
    def checksum_alg(self):
        return self._variant_info[self.variant][0]

    @property
    def checksum_size(self):
        return self._variant_info[self.variant][1]

    #===================================================================
    # formatting
    #===================================================================

    _hash_regex = re.compile(u(r"""
            ^
            \{FSHP
            (\d+)\| # variant
            (\d+)\| # salt size
            (\d+)\} # rounds
            ([a-zA-Z0-9+/]+={0,3}) # digest
            $"""), re.X)

    @classmethod
    def from_string(cls, hash):
        hash = to_unicode(hash, "ascii", "hash")
        m = cls._hash_regex.match(hash)
        if not m:
            raise uh.exc.InvalidHashError(cls)
        variant, salt_size, rounds, data = m.group(1,2,3,4)
        variant = int(variant)
        salt_size = int(salt_size)
        rounds = int(rounds)
        try:
            data = b64decode(data.encode("ascii"))
        except TypeError:
            raise uh.exc.MalformedHashError(cls)
        salt = data[:salt_size]
        chk = data[salt_size:]
        return cls(salt=salt, checksum=chk, rounds=rounds, variant=variant)

    def to_string(self):
        chk = self.checksum
        salt = self.salt
        data = bascii_to_str(b64encode(salt+chk))
        return "{FSHP%d|%d|%d}%s" % (self.variant, len(salt), self.rounds, data)

    #===================================================================
    # backend
    #===================================================================

    def _calc_checksum(self, secret):
        if isinstance(secret, unicode):
            secret = secret.encode("utf-8")
        # NOTE: for some reason, FSHP uses pbkdf1 with password & salt reversed.
        #       this has only a minimal impact on security,
        #       but it is worth noting this deviation.
        return pbkdf1(
            digest=self.checksum_alg,
            secret=self.salt,
            salt=secret,
            rounds=self.rounds,
            keylen=self.checksum_size,
            )
예제 #12
0
 def _iter_lines(self):
     """iterator yielding lines of database"""
     return (self._render_record(key, value)
             for key, value in iteritems(self._records))