view MoinMoin/support/passlib/ifc.py @ 6111:1fdd537e9d83

SubProcess: reimplement exec_cmd subclassing Popen and overriding some methods isn't pretty. the code we have was written for py 2.4 or so and the py 2.7 Popen looked quite different. this way with the timer should be less problematic.
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Tue, 06 Sep 2016 04:39:28 +0200
parents 86a41c2bedec
children 7f0616feeae9
line wrap: on
line source
"""passlib.ifc - abstract interfaces used by Passlib"""
#=============================================================================
# imports
#=============================================================================
# core
import logging; log = logging.getLogger(__name__)
import sys
# site
# pkg
# local
__all__ = [
    "PasswordHash",
]

#=============================================================================
# 2.5-3.2 compatibility helpers
#=============================================================================
if sys.version_info >= (2,6):
    from abc import ABCMeta, abstractmethod, abstractproperty
else:
    # create stub for python 2.5
    ABCMeta = type
    def abstractmethod(func):
        return func
#    def abstractproperty():
#        return None

def create_with_metaclass(meta):
    """class decorator that re-creates class using metaclass"""
    # have to do things this way since abc not present in py25,
    # and py2/py3 have different ways of doing metaclasses.
    def builder(cls):
        if meta is type(cls):
            return cls
        return meta(cls.__name__, cls.__bases__, cls.__dict__.copy())
    return builder

#=============================================================================
# PasswordHash interface
#=============================================================================
class PasswordHash(object):
    """This class describes an abstract interface which all password hashes
    in Passlib adhere to. Under Python 2.6 and up, this is an actual
    Abstract Base Class built using the :mod:`!abc` module.

    See the Passlib docs for full documentation.
    """
    #===================================================================
    # class attributes
    #===================================================================

    #---------------------------------------------------------------
    # general information
    #---------------------------------------------------------------
    ##name
    ##setting_kwds
    ##context_kwds

    #---------------------------------------------------------------
    # salt information -- if 'salt' in setting_kwds
    #---------------------------------------------------------------
    ##min_salt_size
    ##max_salt_size
    ##default_salt_size
    ##salt_chars
    ##default_salt_chars

    #---------------------------------------------------------------
    # rounds information -- if 'rounds' in setting_kwds
    #---------------------------------------------------------------
    ##min_rounds
    ##max_rounds
    ##default_rounds
    ##rounds_cost

    #---------------------------------------------------------------
    # encoding info -- if 'encoding' in context_kwds
    #---------------------------------------------------------------
    ##default_encoding

    #===================================================================
    # primary methods
    #===================================================================
    @classmethod
    @abstractmethod
    def encrypt(cls, secret, **setting_and_context_kwds): # pragma: no cover -- abstract method
        """encrypt secret, returning resulting hash"""
        raise NotImplementedError("must be implemented by subclass")

    @classmethod
    @abstractmethod
    def verify(cls, secret, hash, **context_kwds): # pragma: no cover -- abstract method
        """verify secret against hash, returns True/False"""
        raise NotImplementedError("must be implemented by subclass")

    #===================================================================
    # additional methods
    #===================================================================
    @classmethod
    @abstractmethod
    def identify(cls, hash): # pragma: no cover -- abstract method
        """check if hash belongs to this scheme, returns True/False"""
        raise NotImplementedError("must be implemented by subclass")

    @classmethod
    @abstractmethod
    def genconfig(cls, **setting_kwds): # pragma: no cover -- abstract method
        """compile settings into a configuration string for genhash()"""
        raise NotImplementedError("must be implemented by subclass")

    @classmethod
    @abstractmethod
    def genhash(cls, secret, config, **context_kwds): # pragma: no cover -- abstract method
        """generated hash for secret, using settings from config/hash string"""
        raise NotImplementedError("must be implemented by subclass")

    #===================================================================
    # undocumented methods / attributes
    #===================================================================
    # the following entry points are used internally by passlib,
    # and aren't documented as part of the exposed interface.
    # they are subject to change between releases,
    # but are documented here so there's a list of them *somewhere*.

    #---------------------------------------------------------------
    # checksum information - defined for many hashes
    #---------------------------------------------------------------
    ## checksum_chars
    ## checksum_size

    #---------------------------------------------------------------
    # CryptContext flags
    #---------------------------------------------------------------

    # hack for bsdi_crypt: if True, causes CryptContext to only generate
    # odd rounds values. assumed False if not defined.
    ## _avoid_even_rounds = False

    ##@classmethod
    ##def _bind_needs_update(cls, **setting_kwds):
    ##    """return helper to detect hashes that need updating.
    ##
    ##    if this method is defined, the CryptContext constructor
    ##    will invoke it with the settings specified for the context.
    ##    this method should return either ``None``, or a callable
    ##    with the signature ``needs_update(hash,secret)->bool``.
    ##
    ##    this ``needs_update`` function should return True if the hash
    ##    should be re-encrypted, whether due to internal
    ##    issues or the specified settings.
    ##
    ##    CryptContext will automatically take care of deprecating
    ##    hashes with insufficient rounds for classes which define fromstring()
    ##    and a rounds attribute - though the requirements for this last
    ##    part may change at some point.
    ##    """

    #---------------------------------------------------------------
    # experimental methods
    #---------------------------------------------------------------

    ##@classmethod
    ##def normhash(cls, hash):
    ##    """helper to clean up non-canonic instances of hash.
    ##    currently only provided by bcrypt() to fix an historical passlib issue.
    ##    """

    # experimental helper to parse hash into components.
    ##@classmethod
    ##def parsehash(cls, hash, checksum=True, sanitize=False):
    ##    """helper to parse hash into components, returns dict"""

    # experiment helper to estimate bitsize of different hashes,
    # implement for GenericHandler, but may be currently be off for some hashes.
    # want to expand this into a way to programmatically compare
    # "strengths" of different hashes and hash algorithms.
    # still needs to have some factor for estimate relative cost per round,
    # ala in the style of the scrypt whitepaper.
    ##@classmethod
    ##def bitsize(cls, **kwds):
    ##    """returns dict mapping component -> bits contributed.
    ##    components currently include checksum, salt, rounds.
    ##    """

    #===================================================================
    # eoc
    #===================================================================

PasswordHash = create_with_metaclass(ABCMeta)(PasswordHash)

#=============================================================================
# eof
#=============================================================================