Example #1
0
    def __init__(self, max_length=None, **kwargs):
        # Fail if passlib is not found.
        if passlib is None:
            raise ImproperlyConfigured(
                "'passlib' is required to use 'PasswordType'")

        # Construct the passlib crypt context.
        self.context = LazyCryptContext(**kwargs)
        self._max_length = max_length
Example #2
0
 def crypt_ctx(self):
     ctx = stack.top
     if ctx is not None:
         if not hasattr(self, '_crypt_ctx'):
             self._crypt_ctx = LazyCryptContext(
                 **current_app.config['PASSLIB_CONTEXT'])
         return self._crypt_ctx
Example #3
0
    def __init__(self, max_length=None, **kwargs):
        # Fail if passlib is not found.
        if passlib is None:
            raise ImproperlyConfigured(
                "'passlib' is required to use 'PasswordType'"
            )

        # Construct the passlib crypt context.
        self.context = LazyCryptContext(**kwargs)

        self._max_length = max_length
Example #4
0
    def test_kwd_constructor(self):
        self.assertFalse(has_crypt_handler("dummy_2"))
        register_crypt_handler_path("dummy_2", "passlib.tests.test_context")

        cc = LazyCryptContext(iter(["dummy_2", "des_crypt"]), deprecated=["des_crypt"])

        self.assertFalse(has_crypt_handler("dummy_2", True))

        self.assertTrue(cc.policy.handler_is_deprecated("des_crypt"))
        self.assertEqual(cc.policy.schemes(), ["dummy_2", "des_crypt"])

        self.assertTrue(has_crypt_handler("dummy_2", True))
    def __init__(self, max_length=None, **kwargs):
        # Fail if passlib is not found.
        if passlib is None:
            raise ImproperlyConfigured(
                "'passlib' is required to use 'PasswordType'"
            )

        # Construct the passlib crypt context.
        self.context = LazyCryptContext(**kwargs)

        if max_length is None:
            max_length = self.calculate_max_length()

        # Set the length to the now-calculated max length.
        self.length = max_length
Example #6
0
    def test_callable_constructor(self):
        self.assertFalse(has_crypt_handler("dummy_2"))
        register_crypt_handler_path("dummy_2", "passlib.tests.test_context")

        def create_policy(flag=False):
            self.assertTrue(flag)
            return CryptPolicy(schemes=iter(["dummy_2", "des_crypt"]), deprecated=["des_crypt"])

        cc = LazyCryptContext(create_policy=create_policy, flag=True)

        self.assertFalse(has_crypt_handler("dummy_2", True))

        self.assertTrue(cc.policy.handler_is_deprecated("des_crypt"))
        self.assertEqual(cc.policy.schemes(), ["dummy_2", "des_crypt"])

        self.assertTrue(has_crypt_handler("dummy_2", True))
Example #7
0
class PasswordType(TypeDecorator):
    impl = Text

    def __init__(self, **kwargs):
        super().__init__()
        self.context = LazyCryptContext(**kwargs)

    def process_bind_param(self, value, dialect):
        return self.coerce(value).hash

    def process_result_value(self, value, dialect):
        return Password(value, self.context)

    def coerce(self, value):
        if isinstance(value, Password):
            return value

        return Password(self.context.hash(value), self.context)
Example #8
0
    "openbsd_context",
    "netbsd_context",
    "freebsd_context",
    "host_context",
]

# =============================================================================
# linux support
# =============================================================================

# known platform names - linux2

linux_context = linux2_context = LazyCryptContext(
    schemes=[
        "sha512_crypt", "sha256_crypt", "md5_crypt", "des_crypt",
        "unix_disabled"
    ],
    deprecated=["des_crypt"],
)

# =============================================================================
# bsd support
# =============================================================================

# known platform names -
#   freebsd2
#   freebsd3
#   freebsd4
#   freebsd5
#   freebsd6
#   freebsd7
class PasswordType(types.TypeDecorator, ScalarCoercible):
    """
    PasswordType hashes passwords as they come into the database and allows
    verifying them using a pythonic interface.

    All keyword arguments (aside from max_length) are forwarded to the
    construction of a `passlib.context.LazyCryptContext` object, which
    also supports deferred configuration via the `onload` callback.


    The following usage will create a password column that will
    automatically hash new passwords as `pbkdf2_sha512` but still compare
    passwords against pre-existing `md5_crypt` hashes. As passwords are
    compared; the password hash in the database will be updated to
    be `pbkdf2_sha512`.

    ::


        class Model(Base):
            password = sa.Column(PasswordType(
                schemes=[
                    'pbkdf2_sha512',
                    'md5_crypt'
                ],

                deprecated=['md5_crypt']
            ))


    Verifying password is as easy as:

    ::

        target = Model()
        target.password = '******'
        # '$5$rounds=80000$H.............'

        target.password == 'b'
        # True


    Lazy configuration of the type with Flask config:

    ::


        import flask

        class User(db.Model):
            __tablename__ = 'user'

            password = db.Column(
                PasswordType(
                    # The returned dictionary is forwarded to the CryptContext
                    onload=lambda **kwargs: dict(
                        schemes=flask.current_app.config['PASSWORD_SCHEMES'],
                        **kwargs
                    ),
                ),
                unique=False,
                nullable=False,
            )

    """

    impl = types.VARBINARY(1024)
    python_type = Password

    def __init__(self, max_length=None, **kwargs):
        # Fail if passlib is not found.
        if passlib is None:
            raise ImproperlyConfigured(
                "'passlib' is required to use 'PasswordType'"
            )

        # Construct the passlib crypt context.
        self.context = LazyCryptContext(**kwargs)

        if max_length is None:
            max_length = self.calculate_max_length()

        # Set the length to the now-calculated max length.
        self.length = max_length

    def calculate_max_length(self):
        # Calculate the largest possible encoded password.
        # name + rounds + salt + hash + ($ * 4) of largest hash
        max_lengths = [1024]
        for name in self.context.schemes():
            scheme = getattr(__import__('passlib.hash').hash, name)
            length = 4 + len(scheme.name)
            length += len(str(getattr(scheme, 'max_rounds', '')))
            length += (getattr(scheme, 'max_salt_size', 0) or 0)
            length += getattr(
                scheme,
                'encoded_checksum_size',
                scheme.checksum_size
            )
            max_lengths.append(length)

        # Return the maximum calculated max length.
        return max(max_lengths)

    def load_dialect_impl(self, dialect):
        if dialect.name == 'postgresql':
            # Use a BYTEA type for postgresql.
            impl = postgresql.BYTEA(self.length)
            return dialect.type_descriptor(impl)
        if dialect.name == 'oracle':
            # Use a RAW type for oracle.
            impl = oracle.RAW(self.length)
            return dialect.type_descriptor(impl)

        # Use a VARBINARY for all other dialects.
        impl = types.VARBINARY(self.length)
        return dialect.type_descriptor(impl)

    def process_bind_param(self, value, dialect):
        if isinstance(value, Password):
            # If were given a password secret; encrypt it.
            if value.secret is not None:
                return self.context.encrypt(value.secret).encode('utf8')

            # Value has already been hashed.
            return value.hash

        if isinstance(value, six.string_types):
            # Assume value has not been hashed.
            return self.context.encrypt(value).encode('utf8')

    def process_result_value(self, value, dialect):
        if value is not None:
            return Password(value, self.context)

    def _coerce(self, value):

        if value is None:
            return

        if not isinstance(value, Password):
            # Hash the password using the default scheme.
            value = self.context.encrypt(value).encode('utf8')
            return Password(value, context=self.context)

        else:
            # If were given a password object; ensure the context is right.
            value.context = weakref.proxy(self.context)

            # If were given a password secret; encrypt it.
            if value.secret is not None:
                value.hash = self.context.encrypt(value.secret).encode('utf8')
                value.secret = None

        return value

    @property
    def python_type(self):
        return self.impl.type.python_type
Example #10
0
class PasswordType(types.TypeDecorator, ConversionBase):

    python_type = Password
    impl = types.VARBINARY(1024)

    def __init__(self, max_length=None, **kwargs):
        self._max_length = max_length
        self.context = LazyCryptContext(**kwargs)

        super(PasswordType, self).__init__()

    @property
    def length(self):
        if self._max_length is None:
            self._max_length = self.calculate_max_length()

        return self._max_length

    def calculate_max_length(self):

        max_lengths = [1024]
        for name in self.context.schemes():
            scheme = getattr(__import__('passlib.hash').hash, name)
            length = 4 + len(scheme.name)
            length += len(str(getattr(scheme, 'max_rounds', '')))
            length += (getattr(scheme, 'max_salt_size', 0) or 0)
            length += getattr(scheme, 'encoded_checksum_size',
                              scheme.checksum_size)
            max_lengths.append(length)

        return max(max_lengths)

    def load_dialect_impl(self, dialect):
        impl = types.VARBINARY(self.length)
        return dialect.type_descriptor(impl)

    def process_bind_param(self, value, dialect):
        if isinstance(value, Password):
            if value.secret is not None:
                return value.context.encrypt(value.secret).encode("utf-8")

            return value.hash

        if isinstance(value, basestring):
            return self.context.encrypt(value).encode("utf-8")

    def process_result_value(self, value, dialect):
        if value is not None:
            return Password(value, self.context)

    def _conversion(self, value):
        if value is None:
            return

        if not isinstance(value, Password):
            value = self.context.encrypt(value).encode("utf-8")
            return Password(value, context=self.context, secret=False)

        else:
            value.context = weakref.proxy(self.context)
            if value.secret:
                value.hash = value.context.encrypt(
                    value.secret).encode("utf-8")
                value.secret = None

            return value
Example #11
0
        # plaintext handlers
        'plaintext',
        'ldap_plaintext',

        # disabled handlers
        'django_disabled',
        'unix_disabled',
        'unix_fallback',
    ]
    for name in excluded:
        schemes.remove(name)

    # return config
    return dict(schemes=schemes, default="sha256_crypt")
master_context = LazyCryptContext(onload=_load_master_config)

#=============================================================================
# for quickly bootstrapping new custom applications
#=============================================================================
custom_app_context = LazyCryptContext(
    # choose some reasonbly strong schemes
    schemes=["sha512_crypt", "sha256_crypt"],

    # set some useful global options
    default="sha256_crypt" if sys_bits < 64 else "sha512_crypt",
    all__vary_rounds = 0.1,

    # set a good starting point for rounds selection
    sha512_crypt__min_rounds = 60000,
    sha256_crypt__min_rounds = 80000,
Example #12
0
from passlib.context import LazyCryptContext

olea_context = LazyCryptContext(schemes=['argon2'],
                                argon2__time_cost=2,
                                argon2__memory_cost=256 * 1024,
                                argon2__parallelism=4)
Example #13
0
from distutils.version import StrictVersion
from passlib.context import LazyCryptContext
import werkzeug

from .handlers import (werkzeug_salted_md5, werkzeug_salted_sha1, 
    werkzeug_salted_sha224, werkzeug_salted_sha256, 
    werkzeug_salted_sha384, werkzeug_salted_sha512)


werkzeug061_context = LazyCryptContext(
    schemes=[
        werkzeug_salted_md5,    
        werkzeug_salted_sha1,
    ],
    default='werkzeug_salted_sha1',
)

werkzeugdev_context = LazyCryptContext(
    schemes=[
        werkzeug_salted_md5,    
        werkzeug_salted_sha1,
        werkzeug_salted_sha224,
        werkzeug_salted_sha256,
        werkzeug_salted_sha384,
        werkzeug_salted_sha512,
    ],
    default='werkzeug_salted_sha1',
)


if StrictVersion('0.6.1') <= StrictVersion(werkzeug.__version__) <= StrictVersion('0.8.3'):
Example #14
0
    def __init__(self, max_length=None, **kwargs):
        self._max_length = max_length
        self.context = LazyCryptContext(**kwargs)

        super(PasswordType, self).__init__()
Example #15
0
 def __init__(self, **kwargs):
     super().__init__()
     self.context = LazyCryptContext(**kwargs)
Example #16
0
class PasswordType(types.TypeDecorator, ScalarCoercible):
    """
    PasswordType hashes passwords as they come into the database and allows
    verifying them using a pythonic interface.

    All keyword arguments (aside from max_length) are forwarded to the
    construction of a `passlib.context.LazyCryptContext` object, which
    also supports deferred configuration via the `onload` callback.


    The following usage will create a password column that will
    automatically hash new passwords as `pbkdf2_sha512` but still compare
    passwords against pre-existing `md5_crypt` hashes. As passwords are
    compared; the password hash in the database will be updated to
    be `pbkdf2_sha512`.

    ::


        class Model(Base):
            password = sa.Column(PasswordType(
                schemes=[
                    'pbkdf2_sha512',
                    'md5_crypt'
                ],

                deprecated=['md5_crypt']
            ))


    Verifying password is as easy as:

    ::

        target = Model()
        target.password = '******'
        # '$5$rounds=80000$H.............'

        target.password == 'b'
        # True


    Lazy configuration of the type with Flask config:

    ::


        import flask

        class User(db.Model):
            __tablename__ = 'user'

            password = db.Column(
                PasswordType(
                    # The returned dictionary is forwarded to the CryptContext
                    onload=lambda **kwargs: dict(
                        schemes=flask.current_app.config['PASSWORD_SCHEMES'],
                        **kwargs
                    ),
                ),
                unique=False,
                nullable=False,
            )

    """

    impl = types.VARBINARY(1024)
    python_type = Password

    def __init__(self, max_length=None, **kwargs):
        # Fail if passlib is not found.
        if passlib is None:
            raise ImproperlyConfigured(
                "'passlib' is required to use 'PasswordType'")

        # Construct the passlib crypt context.
        self.context = LazyCryptContext(**kwargs)

        self._max_length = max_length

    def __repr__(self):
        return 'PasswordType(max_length={length})'.format(length=self.length)

    @property
    def length(self):
        """Get column length."""
        if self._max_length is None:
            self._max_length = self.calculate_max_length()

        return self._max_length

    def calculate_max_length(self):
        # Calculate the largest possible encoded password.
        # name + rounds + salt + hash + ($ * 4) of largest hash
        max_lengths = [1024]
        for name in self.context.schemes():
            scheme = getattr(__import__('passlib.hash').hash, name)
            length = 4 + len(scheme.name)
            length += len(str(getattr(scheme, 'max_rounds', '')))
            length += (getattr(scheme, 'max_salt_size', 0) or 0)
            length += getattr(scheme, 'encoded_checksum_size',
                              scheme.checksum_size)
            max_lengths.append(length)

        # Return the maximum calculated max length.
        return max(max_lengths)

    def load_dialect_impl(self, dialect):
        if dialect.name == 'postgresql':
            # Use a BYTEA type for postgresql.
            impl = postgresql.BYTEA(self.length)
            return dialect.type_descriptor(impl)
        if dialect.name == 'oracle':
            # Use a RAW type for oracle.
            impl = oracle.RAW(self.length)
            return dialect.type_descriptor(impl)

        # Use a VARBINARY for all other dialects.
        impl = types.VARBINARY(self.length)
        return dialect.type_descriptor(impl)

    def process_bind_param(self, value, dialect):
        if isinstance(value, Password):
            # If were given a password secret; encrypt it.
            if value.secret is not None:
                return self.context.encrypt(value.secret).encode('utf8')

            # Value has already been hashed.
            return value.hash

        if isinstance(value, six.string_types):
            # Assume value has not been hashed.
            return self.context.encrypt(value).encode('utf8')

    def process_result_value(self, value, dialect):
        if value is not None:
            return Password(value, self.context)

    def _coerce(self, value):

        if value is None:
            return

        if not isinstance(value, Password):
            # Hash the password using the default scheme.
            value = self.context.encrypt(value).encode('utf8')
            return Password(value, context=self.context)

        else:
            # If were given a password object; ensure the context is right.
            value.context = weakref.proxy(self.context)

            # If were given a password secret; encrypt it.
            if value.secret is not None:
                value.hash = self.context.encrypt(value.secret).encode('utf8')
                value.secret = None

        return value

    @property
    def python_type(self):
        return self.impl.type.python_type
Example #17
0
from passlib.context import LazyCryptContext

from {{ cookiecutter.repo_name }}.models.types.password import Password

context = LazyCryptContext(schemes=[
    'md5_crypt'
])

def test_password():
    pwd = Password(context.hash("test_password"), context)

    assert pwd == "test_password", "Comparing against plaintext should work"
    assert pwd != "wrong_password", "not equals should work"