Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
ifc.py354 linesDownload Raw Back to passlib
1"""passlib.ifc - abstract interfaces used by Passlib"""2#=============================================================================3# imports4#=============================================================================5# core6import logging; log = logging.getLogger(__name__)7import sys8# site9# pkg10from passlib.utils.decor import deprecated_method11# local12__all__ = [13    "PasswordHash",14]15 16#=============================================================================17# 2/3 compatibility helpers18#=============================================================================19def recreate_with_metaclass(meta):20    """class decorator that re-creates class using metaclass"""21    def builder(cls):22        if meta is type(cls):23            return cls24        return meta(cls.__name__, cls.__bases__, cls.__dict__.copy())25    return builder26 27#=============================================================================28# PasswordHash interface29#=============================================================================30from abc import ABCMeta, abstractmethod, abstractproperty31 32# TODO: make this actually use abstractproperty(),33#       now that we dropped py25, 'abc' is always available.34 35# XXX: rename to PasswordHasher?36 37@recreate_with_metaclass(ABCMeta)38class PasswordHash(object):39    """This class describes an abstract interface which all password hashes40    in Passlib adhere to. Under Python 2.6 and up, this is an actual41    Abstract Base Class built using the :mod:`!abc` module.42 43    See the Passlib docs for full documentation.44    """45    #===================================================================46    # class attributes47    #===================================================================48 49    #---------------------------------------------------------------50    # general information51    #---------------------------------------------------------------52    ##name53    ##setting_kwds54    ##context_kwds55 56    #: flag which indicates this hasher matches a "disabled" hash57    #: (e.g. unix_disabled, or django_disabled); and doesn't actually58    #: depend on the provided password.59    is_disabled = False60 61    #: Should be None, or a positive integer indicating hash62    #: doesn't support secrets larger than this value.63    #: Whether hash throws error or silently truncates secret64    #: depends on .truncate_error and .truncate_verify_reject flags below.65    #: NOTE: calls may treat as boolean, since value will never be 0.66    #: .. versionadded:: 1.767    #: .. TODO: passlib 1.8: deprecate/rename this attr to "max_secret_size"?68    truncate_size = None69 70    # NOTE: these next two default to the optimistic "ideal",71    #       most hashes in passlib have to default to False72    #       for backward compat and/or expected behavior with existing hashes.73 74    #: If True, .hash() should throw a :exc:`~passlib.exc.PasswordSizeError` for75    #: any secrets larger than .truncate_size.  Many hashers default to False76    #: for historical / compatibility purposes, indicating they will silently77    #: truncate instead.  All such hashers SHOULD support changing78    #: the policy via ``.using(truncate_error=True)``.79    #: .. versionadded:: 1.780    #: .. TODO: passlib 1.8: deprecate/rename this attr to "truncate_hash_error"?81    truncate_error = True82 83    #: If True, .verify() should reject secrets larger than max_password_size.84    #: Many hashers default to False for historical / compatibility purposes,85    #: indicating they will match on the truncated portion instead.86    #: .. versionadded:: 1.7.187    truncate_verify_reject = True88 89    #---------------------------------------------------------------90    # salt information -- if 'salt' in setting_kwds91    #---------------------------------------------------------------92    ##min_salt_size93    ##max_salt_size94    ##default_salt_size95    ##salt_chars96    ##default_salt_chars97 98    #---------------------------------------------------------------99    # rounds information -- if 'rounds' in setting_kwds100    #---------------------------------------------------------------101    ##min_rounds102    ##max_rounds103    ##default_rounds104    ##rounds_cost105 106    #---------------------------------------------------------------107    # encoding info -- if 'encoding' in context_kwds108    #---------------------------------------------------------------109    ##default_encoding110 111    #===================================================================112    # primary methods113    #===================================================================114    @classmethod115    @abstractmethod116    def hash(cls, secret,  # *117             **setting_and_context_kwds):  # pragma: no cover -- abstract method118        r"""119        Hash secret, returning result.120        Should handle generating salt, etc, and should return string121        containing identifier, salt & other configuration, as well as digest.122 123        :param \\*\\*settings_kwds:124 125            Pass in settings to customize configuration of resulting hash.126 127            .. deprecated:: 1.7128 129                Starting with Passlib 1.7, callers should no longer pass settings keywords130                (e.g. ``rounds`` or ``salt`` directly to :meth:`!hash`); should use131                ``.using(**settings).hash(secret)`` construction instead.132 133                Support will be removed in Passlib 2.0.134 135        :param \\*\\*context_kwds:136 137            Specific algorithms may require context-specific information (such as the user login).138        """139        # FIXME:  need stub for classes that define .encrypt() instead ...140        #         this should call .encrypt(), and check for recursion back to here.141        raise NotImplementedError("must be implemented by subclass")142 143    @deprecated_method(deprecated="1.7", removed="2.0", replacement=".hash()")144    @classmethod145    def encrypt(cls, *args, **kwds):146        """147        Legacy alias for :meth:`hash`.148 149        .. deprecated:: 1.7150            This method was renamed to :meth:`!hash` in version 1.7.151            This alias will be removed in version 2.0, and should only152            be used for compatibility with Passlib 1.3 - 1.6.153        """154        return cls.hash(*args, **kwds)155 156    # XXX: could provide default implementation which hands value to157    #      hash(), and then does constant-time comparision on the result158    #      (after making both are same string type)159    @classmethod160    @abstractmethod161    def verify(cls, secret, hash, **context_kwds): # pragma: no cover -- abstract method162        """verify secret against hash, returns True/False"""163        raise NotImplementedError("must be implemented by subclass")164 165    #===================================================================166    # configuration167    #===================================================================168    @classmethod169    @abstractmethod170    def using(cls, relaxed=False, **kwds):171        """172        Return another hasher object (typically a subclass of the current one),173        which integrates the configuration options specified by ``kwds``.174        This should *always* return a new object, even if no configuration options are changed.175 176        .. todo::177 178            document which options are accepted.179 180        :returns:181            typically returns a subclass for most hasher implementations.182 183        .. todo::184 185            add this method to main documentation.186        """187        raise NotImplementedError("must be implemented by subclass")188 189    #===================================================================190    # migration191    #===================================================================192    @classmethod193    def needs_update(cls, hash, secret=None):194        """195        check if hash's configuration is outside desired bounds,196        or contains some other internal option which requires197        updating the password hash.198 199        :param hash:200            hash string to examine201 202        :param secret:203            optional secret known to have verified against the provided hash.204            (this is used by some hashes to detect legacy algorithm mistakes).205 206        :return:207            whether secret needs re-hashing.208 209        .. versionadded:: 1.7210        """211        # by default, always report that we don't need update212        return False213 214    #===================================================================215    # additional methods216    #===================================================================217    @classmethod218    @abstractmethod219    def identify(cls, hash): # pragma: no cover -- abstract method220        """check if hash belongs to this scheme, returns True/False"""221        raise NotImplementedError("must be implemented by subclass")222 223    @deprecated_method(deprecated="1.7", removed="2.0")224    @classmethod225    def genconfig(cls, **setting_kwds): # pragma: no cover -- abstract method226        """227        compile settings into a configuration string for genhash()228 229        .. deprecated:: 1.7230 231            As of 1.7, this method is deprecated, and slated for complete removal in Passlib 2.0.232 233            For all known real-world uses, hashing a constant string234            should provide equivalent functionality.235 236            This deprecation may be reversed if a use-case presents itself in the mean time.237        """238        # NOTE: this fallback runs full hash alg, w/ whatever cost param is passed along.239        #       implementations (esp ones w/ variable cost) will want to subclass this240        #       with a constant-time implementation that just renders a config string.241        if cls.context_kwds:242            raise NotImplementedError("must be implemented by subclass")243        return cls.using(**setting_kwds).hash("")244 245    @deprecated_method(deprecated="1.7", removed="2.0")246    @classmethod247    def genhash(cls, secret, config, **context):248        """249        generated hash for secret, using settings from config/hash string250 251        .. deprecated:: 1.7252 253            As of 1.7, this method is deprecated, and slated for complete removal in Passlib 2.0.254 255            This deprecation may be reversed if a use-case presents itself in the mean time.256        """257        # XXX: if hashes reliably offered a .parse() method, could make a fallback for this.258        raise NotImplementedError("must be implemented by subclass")259 260    #===================================================================261    # undocumented methods / attributes262    #===================================================================263    # the following entry points are used internally by passlib,264    # and aren't documented as part of the exposed interface.265    # they are subject to change between releases,266    # but are documented here so there's a list of them *somewhere*.267 268    #---------------------------------------------------------------269    # extra metdata270    #---------------------------------------------------------------271 272    #: this attribute shouldn't be used by hashers themselves,273    #: it's reserved for the CryptContext to track which hashers are deprecated.274    #: Note the context will only set this on objects it owns (and generated by .using()),275    #: and WONT set it on global objects.276    #: [added in 1.7]277    #: TODO: document this, or at least the use of testing for278    #:       'CryptContext().handler().deprecated'279    deprecated = False280 281    #: optionally present if hasher corresponds to format built into Django.282    #: this attribute (if not None) should be the Django 'algorithm' name.283    #: also indicates to passlib.ext.django that (when installed in django),284    #: django's native hasher should be used in preference to this one.285    ## django_name286 287    #---------------------------------------------------------------288    # checksum information - defined for many hashes289    #---------------------------------------------------------------290    ## checksum_chars291    ## checksum_size292 293    #---------------------------------------------------------------294    # experimental methods295    #---------------------------------------------------------------296 297    ##@classmethod298    ##def normhash(cls, hash):299    ##    """helper to clean up non-canonic instances of hash.300    ##    currently only provided by bcrypt() to fix an historical passlib issue.301    ##    """302 303    # experimental helper to parse hash into components.304    ##@classmethod305    ##def parsehash(cls, hash, checksum=True, sanitize=False):306    ##    """helper to parse hash into components, returns dict"""307 308    # experiment helper to estimate bitsize of different hashes,309    # implement for GenericHandler, but may be currently be off for some hashes.310    # want to expand this into a way to programmatically compare311    # "strengths" of different hashes and hash algorithms.312    # still needs to have some factor for estimate relative cost per round,313    # ala in the style of the scrypt whitepaper.314    ##@classmethod315    ##def bitsize(cls, **kwds):316    ##    """returns dict mapping component -> bits contributed.317    ##    components currently include checksum, salt, rounds.318    ##    """319 320    #===================================================================321    # eoc322    #===================================================================323 324class DisabledHash(PasswordHash):325    """326    extended disabled-hash methods; only need be present if .disabled = True327    """328 329    is_disabled = True330 331    @classmethod332    def disable(cls, hash=None):333        """334        return string representing a 'disabled' hash;335        optionally including previously enabled hash336        (this is up to the individual scheme).337        """338        # default behavior: ignore original hash, return standalone marker339        return cls.hash("")340 341    @classmethod342    def enable(cls, hash):343        """344        given a disabled-hash string,345        extract previously-enabled hash if one is present,346        otherwise raises ValueError347        """348        # default behavior: no way to restore original hash349        raise ValueError("cannot restore original hash")350 351#=============================================================================352# eof353#=============================================================================354 
codekingpro/portable-devtools · Team Ai