Example #1
0
    def test_pbkdf2_upgrade_new_hasher(self):
        self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
        hasher = get_hasher('default')
        self.assertNotEqual(hasher.iterations, 1)

        state = {'upgraded': False}

        def setter(password):
            state['upgraded'] = True

        with self.settings(PASSWORD_HASHERS=[
                'django.contrib.auth.tests.test_hashers.PBKDF2SingleIterationHasher'
        ]):
            encoded = make_password('letmein')
            algo, iterations, salt, hash = encoded.split('$', 3)
            self.assertEqual(iterations, '1')

            # Check that no upgrade is triggerd
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertFalse(state['upgraded'])

        # Revert to the old iteration count and check if the password would get
        # updated to the new iteration count.
        with self.settings(PASSWORD_HASHERS=[
                'django.contrib.auth.hashers.PBKDF2PasswordHasher',
                'django.contrib.auth.tests.test_hashers.PBKDF2SingleIterationHasher'
        ]):
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertTrue(state['upgraded'])
Example #2
0
    def test_pbkdf2_upgrade(self):
        self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
        hasher = get_hasher('default')
        self.assertNotEqual(hasher.iterations, 1)

        old_iterations = hasher.iterations
        try:
            # Generate a password with 1 iteration.
            hasher.iterations = 1
            encoded = make_password('letmein')
            algo, iterations, salt, hash = encoded.split('$', 3)
            self.assertEqual(iterations, '1')

            state = {'upgraded': False}

            def setter(password):
                state['upgraded'] = True

            # Check that no upgrade is triggerd
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertFalse(state['upgraded'])

            # Revert to the old iteration count and ...
            hasher.iterations = old_iterations

            # ... check if the password would get updated to the new iteration count.
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertTrue(state['upgraded'])
        finally:
            hasher.iterations = old_iterations
Example #3
0
    def render(self, name, value, attrs):
        encoded = value

        if not is_password_usable(encoded):
            return "None"

        final_attrs = self.build_attrs(attrs)

        encoded = smart_str(encoded)

        if len(encoded) == 32 and '$' not in encoded:
            hasher = get_hasher('md5')
        else:
            algorithm = encoded.split('$', 1)[0]
            hasher = get_hasher(algorithm)

        summary = ""
        for key, value in hasher.safe_summary(encoded).iteritems():
            summary += "<strong>%(key)s</strong>: %(value)s " % {
                "key": key,
                "value": value
            }

        return mark_safe("<div%(attrs)s>%(summary)s</div>" % {
            "attrs": flatatt(final_attrs),
            "summary": summary
        })
Example #4
0
    def test_pbkdf2_upgrade_new_hasher(self):
        self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
        hasher = get_hasher('default')
        self.assertNotEqual(hasher.iterations, 1)

        state = {'upgraded': False}

        def setter(password):
            state['upgraded'] = True

        with self.settings(PASSWORD_HASHERS=[
                'django.contrib.auth.tests.test_hashers.PBKDF2SingleIterationHasher']):
            encoded = make_password('letmein')
            algo, iterations, salt, hash = encoded.split('$', 3)
            self.assertEqual(iterations, '1')

            # Check that no upgrade is triggerd
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertFalse(state['upgraded'])

        # Revert to the old iteration count and check if the password would get
        # updated to the new iteration count.
        with self.settings(PASSWORD_HASHERS=[
                'django.contrib.auth.hashers.PBKDF2PasswordHasher',
                'django.contrib.auth.tests.test_hashers.PBKDF2SingleIterationHasher']):
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertTrue(state['upgraded'])
Example #5
0
    def test_pbkdf2_upgrade(self):
        self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
        hasher = get_hasher('default')
        self.assertNotEqual(hasher.iterations, 1)

        old_iterations = hasher.iterations
        try:
            # Generate a password with 1 iteration.
            hasher.iterations = 1
            encoded = make_password('letmein')
            algo, iterations, salt, hash = encoded.split('$', 3)
            self.assertEqual(iterations, '1')

            state = {'upgraded': False}
            def setter(password):
                state['upgraded'] = True

            # Check that no upgrade is triggerd
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertFalse(state['upgraded'])

            # Revert to the old iteration count and ...
            hasher.iterations = old_iterations

            # ... check if the password would get updated to the new iteration count.
            self.assertTrue(check_password('letmein', encoded, setter))
            self.assertTrue(state['upgraded'])
        finally:
            hasher.iterations = old_iterations
Example #6
0
    def _create_django_hasher(self, django_name):
        """
        helper to create new django hasher by name.
        wraps underlying django methods.
        """
        # if we haven't patched django, can use it directly
        module = sys.modules.get("passlib.ext.django.models")
        if module is None or not module.adapter.patched:
            from django.contrib.auth.hashers import get_hasher
            return get_hasher(django_name)

        # We've patched django's get_hashers(), so calling django's get_hasher()
        # or get_hashers_by_algorithm() would only land us back here.
        # As non-ideal workaround, have to use original get_hashers(),
        get_hashers = module.adapter._manager.getorig("django.contrib.auth.hashers:get_hashers").__wrapped__
        for hasher in get_hashers():
            if hasher.algorithm == django_name:
                return hasher

        # hardcode a few for cases where get_hashers() look won't work.
        path = self._builtin_django_hashers.get(django_name)
        if path:
            if "." not in path:
                path = "django.contrib.auth.hashers." + path
            from django.utils.module_loading import import_string
            return import_string(path)()

        raise ValueError("unknown hasher: %r" % django_name)
def demote_user(username):

    target_user = User.objects.filter(username=username)
    assert len(target_user) == 1 , \
            "There is no such user or the database is corrupted"

    hasher = get_hasher('pph')
    hasher.load()

    # for safety purposes, we will scan the database to guarantee that there
    # is already a threshold of users in order to recover the secert after
    # unlocking.
    target_threshold = hasher.threshold
    number_of_threshold_accounts = 0
    all_users = User.objects.all()
    for user in all_users:
        sharenumber = user.password.split('$')[1]
        sharenumber = int(sharenumber)
        if sharenumber > 0:
            number_of_threshold_accounts += 1


    assert number_of_threshold_accounts > target_threshold

    # now, perform the demotion
    for user in target_user:

        encoded = user.password
        new_password = hasher.demote_hash(encoded)
        user.password = new_password
        user.save()
Example #8
0
    def _test_scrypt_upgrade(self, attr, summary_key, new_value):
        hasher = get_hasher("scrypt")
        self.assertEqual(hasher.algorithm, "scrypt")
        self.assertNotEqual(getattr(hasher, attr), new_value)

        old_value = getattr(hasher, attr)
        try:
            # Generate hash with attr set to the new value.
            setattr(hasher, attr, new_value)
            encoded = make_password("lètmein", "seasalt", "scrypt")
            attr_value = hasher.safe_summary(encoded)[summary_key]
            self.assertEqual(attr_value, new_value)

            state = {"upgraded": False}

            def setter(password):
                state["upgraded"] = True

            # No update is triggered.
            self.assertIs(check_password("lètmein", encoded, setter, "scrypt"),
                          True)
            self.assertIs(state["upgraded"], False)
            # Revert to the old value.
            setattr(hasher, attr, old_value)
            # Password is updated.
            self.assertIs(check_password("lètmein", encoded, setter, "scrypt"),
                          True)
            self.assertIs(state["upgraded"], True)
        finally:
            setattr(hasher, attr, old_value)
Example #9
0
    def new(self, request):
        user = request.user
        hasher = get_hasher("default")
        nana = ExternalNewSerializer(data=request.data)
        if nana.is_valid():
            accesstoken = user.id  # TODO: THIS should be a unique string for every user, their own private secret
            uniqueexternalid = hasher.encode(accesstoken,
                                             nana.validated_data["name"])
        else:
            raise ValidationError("Something is wrong here")

        # Checking if this external already exists in Data
        external = External.objects.filter(uniqueid=uniqueexternalid)
        if not external.exists():
            newexternaldict = copy.copy(request.data)
            newexternaldict["uniqueid"] = uniqueexternalid
            newexternal = ExternalSerializer(data=newexternaldict)
            if newexternal.is_valid():
                instance = newexternal.save()
                self.publish(newexternal, "create")
                return Response(newexternal.data)
            else:
                raise ValidationError("You didnt provide the correct data")

        else:
            newexternal = ExternalSerializer(external.first())
            self.publish(newexternal, "update")
            return Response(newexternal.data)
Example #10
0
    def test_check_password_upgrade(self):
        """Don't update password if adjusting hash iteration

        password_changed() shouldn't be called if User.check_password()
        triggers a hash iteration upgrade.
        """
        user = User.objects.create_user(email="*****@*****.**",
                                        password="******")
        initial_password = user.password
        self.assertTrue(user.check_password("foo"))
        hasher = get_hasher("default")
        self.assertEqual("pbkdf2_sha256", hasher.algorithm)

        old_iterations = hasher.iterations
        try:
            # Upgrade the password iterations
            hasher.iterations = old_iterations + 1
            with patch(
                    "django.contrib.auth.password_validation.password_changed",
            ) as pw_changed:
                user.check_password("foo")
                self.assertEqual(pw_changed.call_count, 0)
            self.assertNotEqual(initial_password, user.password)
        finally:
            hasher.iterations = old_iterations
Example #11
0
    def test_bcrypt_upgrade(self):
        hasher = get_hasher("bcrypt")
        self.assertEqual("bcrypt", hasher.algorithm)
        self.assertNotEqual(hasher.rounds, 4)

        old_rounds = hasher.rounds
        try:
            # Generate a password with 4 rounds.
            hasher.rounds = 4
            encoded = make_password("letmein", hasher="bcrypt")
            rounds = hasher.safe_summary(encoded)["work factor"]
            self.assertEqual(rounds, "04")

            state = {"upgraded": False}

            def setter(password):
                state["upgraded"] = True

            # Check that no upgrade is triggered.
            self.assertTrue(check_password("letmein", encoded, setter, "bcrypt"))
            self.assertFalse(state["upgraded"])

            # Revert to the old rounds count and ...
            hasher.rounds = old_rounds

            # ... check if the password would get updated to the new count.
            self.assertTrue(check_password("letmein", encoded, setter, "bcrypt"))
            self.assertTrue(state["upgraded"])
        finally:
            hasher.rounds = old_rounds
Example #12
0
    def test_pbkdf2_upgrade(self):
        hasher = get_hasher("default")
        self.assertEqual("pbkdf2_sha256", hasher.algorithm)
        self.assertNotEqual(hasher.iterations, 1)

        old_iterations = hasher.iterations
        try:
            # Generate a password with 1 iteration.
            hasher.iterations = 1
            encoded = make_password("letmein")
            algo, iterations, salt, hash = encoded.split("$", 3)
            self.assertEqual(iterations, "1")

            state = {"upgraded": False}

            def setter(password):
                state["upgraded"] = True

            # Check that no upgrade is triggered
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertFalse(state["upgraded"])

            # Revert to the old iteration count and ...
            hasher.iterations = old_iterations

            # ... check if the password would get updated to the new iteration count.
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertTrue(state["upgraded"])
        finally:
            hasher.iterations = old_iterations
    def render(self, name, value, attrs):
        encoded = value

        if not is_password_usable(encoded):
            return "None"

        final_attrs = self.build_attrs(attrs)

        encoded = smart_str(encoded)

        if len(encoded) == 32 and '$' not in encoded:
            algorithm = 'unsalted_md5'
        else:
            algorithm = encoded.split('$', 1)[0]

        try:
            hasher = get_hasher(algorithm)
        except ValueError:
            summary = "<strong>Invalid password format or unknown hashing algorithm.</strong>"
        else:
            summary = ""
            for key, value in hasher.safe_summary(encoded).iteritems():
                summary += "<strong>%(key)s</strong>: %(value)s " % {"key": ugettext(key), "value": value}

        return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary})
Example #14
0
    def _test_argon2_upgrade(self, attr, summary_key, new_value):
        hasher = get_hasher('argon2')
        self.assertEqual('argon2', hasher.algorithm)
        self.assertNotEqual(getattr(hasher, attr), new_value)

        old_value = getattr(hasher, attr)
        try:
            # Generate hash with attr set to 1
            setattr(hasher, attr, new_value)
            encoded = make_password('letmein', hasher='argon2')
            attr_value = hasher.safe_summary(encoded)[summary_key]
            self.assertEqual(attr_value, new_value)

            state = {'upgraded': False}

            def setter(password):
                state['upgraded'] = True

            # Check that no upgrade is triggered.
            self.assertTrue(check_password('letmein', encoded, setter, 'argon2'))
            self.assertFalse(state['upgraded'])

            # Revert to the old rounds count and ...
            setattr(hasher, attr, old_value)

            # ... check if the password would get updated to the new count.
            self.assertTrue(check_password('letmein', encoded, setter, 'argon2'))
            self.assertTrue(state['upgraded'])
        finally:
            setattr(hasher, attr, old_value)
Example #15
0
    def test_bcrypt_upgrade(self):
        hasher = get_hasher('bcrypt')
        self.assertEqual('bcrypt', hasher.algorithm)
        self.assertNotEqual(hasher.rounds, 4)

        old_rounds = hasher.rounds
        try:
            # Generate a password with 4 rounds.
            hasher.rounds = 4
            encoded = make_password('letmein', hasher='bcrypt')
            rounds = hasher.safe_summary(encoded)['work factor']
            self.assertEqual(rounds, '04')

            state = {'upgraded': False}

            def setter(password):
                state['upgraded'] = True

            # Check that no upgrade is triggered.
            self.assertTrue(check_password('letmein', encoded, setter, 'bcrypt'))
            self.assertFalse(state['upgraded'])

            # Revert to the old rounds count and ...
            hasher.rounds = old_rounds

            # ... check if the password would get updated to the new count.
            self.assertTrue(check_password('letmein', encoded, setter, 'bcrypt'))
            self.assertTrue(state['upgraded'])
        finally:
            hasher.rounds = old_rounds
Example #16
0
    def _test_argon2_upgrade(self, attr, summary_key, new_value):
        hasher = get_hasher("argon2")
        self.assertEqual("argon2", hasher.algorithm)
        self.assertNotEqual(getattr(hasher, attr), new_value)

        old_value = getattr(hasher, attr)
        try:
            # Generate hash with attr set to 1
            setattr(hasher, attr, new_value)
            encoded = make_password("letmein", hasher="argon2")
            attr_value = hasher.safe_summary(encoded)[summary_key]
            self.assertEqual(attr_value, new_value)

            state = {"upgraded": False}

            def setter(password):
                state["upgraded"] = True

            # No upgrade is triggered.
            self.assertTrue(
                check_password("letmein", encoded, setter, "argon2"))
            self.assertFalse(state["upgraded"])

            # Revert to the old rounds count and ...
            setattr(hasher, attr, old_value)

            # ... check if the password would get updated to the new count.
            self.assertTrue(
                check_password("letmein", encoded, setter, "argon2"))
            self.assertTrue(state["upgraded"])
        finally:
            setattr(hasher, attr, old_value)
Example #17
0
    def test_bcrypt_upgrade(self):
        hasher = get_hasher("bcrypt")
        self.assertEqual("bcrypt", hasher.algorithm)
        self.assertNotEqual(hasher.rounds, 4)

        old_rounds = hasher.rounds
        try:
            # Generate a password with 4 rounds.
            hasher.rounds = 4
            encoded = make_password("letmein", hasher="bcrypt")
            rounds = hasher.safe_summary(encoded)["work factor"]
            self.assertEqual(rounds, 4)

            state = {"upgraded": False}

            def setter(password):
                state["upgraded"] = True

            # No upgrade is triggered.
            self.assertTrue(
                check_password("letmein", encoded, setter, "bcrypt"))
            self.assertFalse(state["upgraded"])

            # Revert to the old rounds count and ...
            hasher.rounds = old_rounds

            # ... check if the password would get updated to the new count.
            self.assertTrue(
                check_password("letmein", encoded, setter, "bcrypt"))
            self.assertTrue(state["upgraded"])
        finally:
            hasher.rounds = old_rounds
Example #18
0
    def clean_password(self):
        hasher = get_hasher(algorithm='sha1')
        hashed_password = hasher.encode(self.cleaned_data['password'],
                                        SALT)

        bingo_boards = BingoBoard.objects.filter(
            password=hashed_password).select_related()

        # check, that no User gets two BingoBoards from the same Game,
        # just because another User used the same password.
        # Games, which contain two BingoBoards with the given password
        # are filtered, so these BingoBoards cannot be claimed by anyone.
        game_ids = set()
        duplicate_game_ids = set()
        for board in bingo_boards:
            if board.game.id in game_ids:
                duplicate_game_ids.add(board.game.id)
            else:
                game_ids.add(board.game.id)

        # filter for user=None to prevent stealing already claimed boards
        bingo_boards.exclude(
            game__id__in=duplicate_game_ids).filter(
            user=None).update(user=self.user)

        return hashed_password
Example #19
0
    def _create_django_hasher(self, django_name):
        """
        helper to create new django hasher by name.
        wraps underlying django methods.
        """
        # if we haven't patched django, can use it directly
        module = sys.modules.get("passlib.ext.django.models")
        if module is None or not module.adapter.patched:
            from django.contrib.auth.hashers import get_hasher
            return get_hasher(django_name)

        # We've patched django's get_hashers(), so calling django's get_hasher()
        # or get_hashers_by_algorithm() would only land us back here.
        # As non-ideal workaround, have to use original get_hashers(),
        get_hashers = module.adapter._manager.getorig("django.contrib.auth.hashers:get_hashers").__wrapped__
        for hasher in get_hashers():
            if hasher.algorithm == django_name:
                return hasher

        # hardcode a few for cases where get_hashers() look won't work.
        path = self._builtin_django_hashers.get(django_name)
        if path:
            if "." not in path:
                path = "django.contrib.auth.hashers." + path
            from django.utils.module_loading import import_string
            return import_string(path)()

        raise ValueError("unknown hasher: %r" % django_name)
Example #20
0
    def test_pbkdf2_upgrade_new_hasher(self):
        hasher = get_hasher("default")
        self.assertEqual("pbkdf2_sha256", hasher.algorithm)
        self.assertNotEqual(hasher.iterations, 1)

        state = {"upgraded": False}

        def setter(password):
            state["upgraded"] = True

        with self.settings(PASSWORD_HASHERS=[
                "auth_tests.test_hashers.PBKDF2SingleIterationHasher"
        ]):
            encoded = make_password("letmein")
            algo, iterations, salt, hash = encoded.split("$", 3)
            self.assertEqual(iterations, "1")

            # No upgrade is triggered
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertFalse(state["upgraded"])

        # Revert to the old iteration count and check if the password would get
        # updated to the new iteration count.
        with self.settings(PASSWORD_HASHERS=[
                "django.contrib.auth.hashers.PBKDF2PasswordHasher",
                "auth_tests.test_hashers.PBKDF2SingleIterationHasher",
        ]):
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertTrue(state["upgraded"])
Example #21
0
    def test_bcrypt_upgrade(self):
        hasher = get_hasher('bcrypt')
        self.assertEqual('bcrypt', hasher.algorithm)
        self.assertNotEqual(hasher.rounds, 4)

        old_rounds = hasher.rounds
        try:
            # Generate a password with 4 rounds.
            hasher.rounds = 4
            encoded = make_password('letmein', hasher='bcrypt')
            rounds = hasher.safe_summary(encoded)['work factor']
            self.assertEqual(rounds, '04')

            state = {'upgraded': False}

            def setter(password):
                state['upgraded'] = True

            # No upgrade is triggered.
            self.assertTrue(check_password('letmein', encoded, setter, 'bcrypt'))
            self.assertFalse(state['upgraded'])

            # Revert to the old rounds count and ...
            hasher.rounds = old_rounds

            # ... check if the password would get updated to the new count.
            self.assertTrue(check_password('letmein', encoded, setter, 'bcrypt'))
            self.assertTrue(state['upgraded'])
        finally:
            hasher.rounds = old_rounds
Example #22
0
 def test_argon2(self):
     encoded = make_password("lètmein", hasher="argon2")
     self.assertTrue(is_password_usable(encoded))
     self.assertTrue(encoded.startswith("argon2$argon2id$"))
     self.assertTrue(check_password("lètmein", encoded))
     self.assertFalse(check_password("lètmeinz", encoded))
     self.assertEqual(identify_hasher(encoded).algorithm, "argon2")
     # Blank passwords
     blank_encoded = make_password("", hasher="argon2")
     self.assertTrue(blank_encoded.startswith("argon2$argon2id$"))
     self.assertTrue(is_password_usable(blank_encoded))
     self.assertTrue(check_password("", blank_encoded))
     self.assertFalse(check_password(" ", blank_encoded))
     # Old hashes without version attribute
     encoded = (
         "argon2$argon2i$m=8,t=1,p=1$c29tZXNhbHQ$gwQOXSNhxiOxPOA0+PY10P9QFO"
         "4NAYysnqRt1GSQLE55m+2GYDt9FEjPMHhP2Cuf0nOEXXMocVrsJAtNSsKyfg")
     self.assertTrue(check_password("secret", encoded))
     self.assertFalse(check_password("wrong", encoded))
     # Old hashes with version attribute.
     encoded = "argon2$argon2i$v=19$m=8,t=1,p=1$c2FsdHNhbHQ$YC9+jJCrQhs5R6db7LlN8Q"
     self.assertIs(check_password("secret", encoded), True)
     self.assertIs(check_password("wrong", encoded), False)
     # Salt entropy check.
     hasher = get_hasher("argon2")
     encoded_weak_salt = make_password("lètmein", "iodizedsalt", "argon2")
     encoded_strong_salt = make_password("lètmein", hasher.salt(), "argon2")
     self.assertIs(hasher.must_update(encoded_weak_salt), True)
     self.assertIs(hasher.must_update(encoded_strong_salt), False)
Example #23
0
def demote_user(username):

    target_user = User.objects.filter(username=username)
    assert len(target_user) == 1,\
        "There is no such user or the database is corrupted"

    hasher = get_hasher('pph')
    hasher.load()

    # for safety purposes, we will scan the database to guarantee that there
    # is already a threshold of users in order to recover the secert after
    # unlocking.
    target_threshold = hasher.threshold
    number_of_threshold_accounts = 0
    all_users = User.objects.all()
    for user in all_users:
        sharenumber = user.password.split('$')[1]
        sharenumber = int(sharenumber)
        if sharenumber > 0:
            number_of_threshold_accounts += 1

    assert number_of_threshold_accounts > target_threshold

    # now, perform the demotion
    for user in target_user:

        encoded = user.password
        new_password = hasher.demote_hash(encoded)
        user.password = new_password
        user.save()
Example #24
0
    def render(self, name, value, attrs):
        encoded = value

        if not is_password_usable(encoded):
            return "None"

        final_attrs = self.build_attrs(attrs)

        encoded = smart_str(encoded)

        if len(encoded) == 32 and '$' not in encoded:
            algorithm = 'unsalted_md5'
        else:
            algorithm = encoded.split('$', 1)[0]

        try:
            hasher = get_hasher(algorithm)
        except ValueError:
            summary = "<strong>Invalid password format or unknown hashing algorithm.</strong>"
        else:
            summary = ""
            for key, value in hasher.safe_summary(encoded).iteritems():
                summary += "<strong>%(key)s</strong>: %(value)s " % {
                    "key": ugettext(key),
                    "value": value
                }

        return mark_safe("<div%(attrs)s>%(summary)s</div>" % {
            "attrs": flatatt(final_attrs),
            "summary": summary
        })
Example #25
0
    def test_pbkdf2_upgrade_new_hasher(self):
        hasher = get_hasher("default")
        self.assertEqual("pbkdf2_sha256", hasher.algorithm)
        self.assertNotEqual(hasher.iterations, 1)

        state = {"upgraded": False}

        def setter(password):
            state["upgraded"] = True

        with self.settings(PASSWORD_HASHERS=["auth_tests.test_hashers.PBKDF2SingleIterationHasher"]):
            encoded = make_password("letmein")
            algo, iterations, salt, hash = encoded.split("$", 3)
            self.assertEqual(iterations, "1")

            # Check that no upgrade is triggered
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertFalse(state["upgraded"])

        # Revert to the old iteration count and check if the password would get
        # updated to the new iteration count.
        with self.settings(
            PASSWORD_HASHERS=[
                "django.contrib.auth.hashers.PBKDF2PasswordHasher",
                "auth_tests.test_hashers.PBKDF2SingleIterationHasher",
            ]
        ):
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertTrue(state["upgraded"])
Example #26
0
    def test_pbkdf2_upgrade(self):
        hasher = get_hasher("default")
        self.assertEqual("pbkdf2_sha256", hasher.algorithm)
        self.assertNotEqual(hasher.iterations, 1)

        old_iterations = hasher.iterations
        try:
            # Generate a password with 1 iteration.
            hasher.iterations = 1
            encoded = make_password("letmein")
            algo, iterations, salt, hash = encoded.split("$", 3)
            self.assertEqual(iterations, "1")

            state = {"upgraded": False}

            def setter(password):
                state["upgraded"] = True

            # No upgrade is triggered
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertFalse(state["upgraded"])

            # Revert to the old iteration count and ...
            hasher.iterations = old_iterations

            # ... check if the password would get updated to the new iteration count.
            self.assertTrue(check_password("letmein", encoded, setter))
            self.assertTrue(state["upgraded"])
        finally:
            hasher.iterations = old_iterations
Example #27
0
 def clean_password(self):
     if self.cleaned_data['password']:
         hasher = get_hasher(algorithm='sha1')
         hashed_password = hasher.encode(
             self.cleaned_data['password'], SALT)
         return hashed_password
     else:
         return None
Example #28
0
 def clean_password(self):
     if self.cleaned_data['password']:
         hasher = get_hasher(algorithm='sha1')
         hashed_password = hasher.encode(self.cleaned_data['password'],
                                         SALT)
         return hashed_password
     else:
         return None
Example #29
0
 def test_no_upgrade_on_incorrect_pass(self):
     self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
     for algo in ('sha1', 'md5'):
         encoded = make_password('lètmein', hasher=algo)
         state = {'upgraded': False}
         def setter():
             state['upgraded'] = True
         self.assertFalse(check_password('WRONG', encoded, setter))
         self.assertFalse(state['upgraded'])
Example #30
0
 def test_upgrade(self):
     self.assertEqual('fastpbkdf2_sha256', get_hasher('default').algorithm)
     for algo in ('sha1', 'md5'):
         encoded = make_password('letmein', hasher=algo)
         state = {'upgraded': False}
         def setter(password):
             state['upgraded'] = True
         self.assertTrue(check_password('letmein', encoded, setter))
         self.assertTrue(state['upgraded'])
Example #31
0
def getPasswordHash(password):
    """Gives the hash of the given password string"""
    if password is None :
        return None
    else:
        hasher = get_hasher('default')
        salt = hasher.salt()
        pass_hash = make_password(password,salt)
        return pass_hash
Example #32
0
 def test_argon2_decode(self):
     salt = 'abcdefghijk'
     encoded = make_password('lètmein', salt=salt, hasher='argon2')
     hasher = get_hasher('argon2')
     decoded = hasher.decode(encoded)
     self.assertEqual(decoded['memory_cost'], hasher.memory_cost)
     self.assertEqual(decoded['parallelism'], hasher.parallelism)
     self.assertEqual(decoded['salt'], salt)
     self.assertEqual(decoded['time_cost'], hasher.time_cost)
Example #33
0
 def test_no_upgrade_on_incorrect_pass(self):
     self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
     for algo in ('sha1', 'md5'):
         encoded = make_password('lètmein', hasher=algo)
         state = {'upgraded': False}
         def setter():
             state['upgraded'] = True
         self.assertFalse(check_password('WRONG', encoded, setter))
         self.assertFalse(state['upgraded'])
Example #34
0
 def test_argon2_decode(self):
     salt = "abcdefghijk"
     encoded = make_password("lètmein", salt=salt, hasher="argon2")
     hasher = get_hasher("argon2")
     decoded = hasher.decode(encoded)
     self.assertEqual(decoded["memory_cost"], hasher.memory_cost)
     self.assertEqual(decoded["parallelism"], hasher.parallelism)
     self.assertEqual(decoded["salt"], salt)
     self.assertEqual(decoded["time_cost"], hasher.time_cost)
Example #35
0
 def handle(self, *args, **options):
     updates = 0
     hasher = get_hasher('unsalted_md5')
     password = make_password('456', '', hasher)
     updates = User.objects.update(password=password)
     print(self.style.SQL_COLTYPE('%d passwords changed to "456"' %
                                  updates))
     self.stdout.write('Successfully %d passwords changed to 456"' %
                       updates)
Example #36
0
    def clean(self):

        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        # see if password is encoded as a hash
        if password:

            # a hash is in the format: <algorithm>$<iterations>$<hash>
            parts = password.split('$')

            if len(parts) >= 3 and len(password) <= 128:

                # most likely a hash
                hasher = get_hasher()

                if parts[0] == hasher.algorithm:

                    # it is a hash, authenticate
                    encoded = password

                    try:

                        # retrieve current password
                        pwd = TemporaryPassword.objects.get(
                            user__username=username)
                        password = pwd.password
                        valid_until = pwd.created_on + timedelta(seconds=120)

                        # invalidate login if password is expired
                        if timezone.now() > valid_until:
                            password = None

                    except ObjectDoesNotExist:

                        password = None

                    # check password
                    if password is not None and check_password(
                            password, encoded):

                        # confirm user login allowed
                        self.confirm_login_allowed(pwd.user)

                        # valid login
                        return self.cleaned_data

                    # otherwise it is an invalid login
                    raise forms.ValidationError(
                        self.error_messages['invalid_login'],
                        code='invalid_login',
                        params={'username': self.username_field.verbose_name},
                    )

        # if not a hash, call super to validate password
        return super().clean()
Example #37
0
 def save(self, *args, **kwargs):
     if (self.org is None and self.user is None):
         raise Exception("You need to provide a user or org as owner")
     elif (self.org is not None and self.user is not None):
         raise Exception("A petition can have only one owner")
     else:
         if not self.salt:
             hasher = get_hasher()
             self.salt = hasher.salt().decode('utf-8')
         super(Petition, self).save(*args, **kwargs)
Example #38
0
def get_required_password_hash_specs():
    """Returns the algorithm and iterations to be used for new password
       hashes"""

    default_hasher = get_hasher()

    return {
        'algo': default_hasher.algorithm,
        'iterations': default_hasher.iterations
    }
Example #39
0
 def set_client_secret(self, password):
     if password is None:
         raise AttributeError('Password can not be empty')
     if self.client_auth_type == self.CLIENT_AUTH_TYPE_SECRET_JWT:
         # need secret in plain text !
         self.client_hashed_secret = password
     else:
         hasher = get_hasher('default')
         salt = hasher.salt()
         self.client_hashed_secret = hasher.encode(password, salt)
Example #40
0
    def test_safesummary(self):
        """ Test to see whether safe_summary works. """
        hasher = get_hasher('legacy')

        self.assertEquals(
            hasher.safe_summary('legacy$fd054714ea93060e80c3cac98ff47a424a2acfd1'),
            {
                'algorithm': 'legacy',
                'hash': 'fd0547**********************************'
            }
        )
Example #41
0
    def test_no_upgrade_on_incorrect_pass(self):
        self.assertEqual("pbkdf2_sha256", get_hasher("default").algorithm)
        for algo in ("sha1", "md5"):
            encoded = make_password("letmein", hasher=algo)
            state = {"upgraded": False}

            def setter():
                state["upgraded"] = True

            self.assertFalse(check_password("WRONG", encoded, setter))
            self.assertFalse(state["upgraded"])
Example #42
0
    def test_upgrade(self):
        self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
        for algo in ('sha1', 'md5'):
            with self.subTest(algo=algo):
                encoded = make_password('lètmein', hasher=algo)
                state = {'upgraded': False}

                def setter(password):
                    state['upgraded'] = True
                self.assertTrue(check_password('lètmein', encoded, setter))
                self.assertTrue(state['upgraded'])
Example #43
0
    def test_check_password_calls_harden_runtime(self):
        hasher = get_hasher("default")
        encoded = make_password("letmein")

        with mock.patch.object(hasher, "harden_runtime"), mock.patch.object(hasher, "must_update", return_value=True):
            # Correct password supplied, no hardening needed
            check_password("letmein", encoded)
            self.assertEqual(hasher.harden_runtime.call_count, 0)

            # Wrong password supplied, hardening needed
            check_password("wrong_password", encoded)
            self.assertEqual(hasher.harden_runtime.call_count, 1)
Example #44
0
def _get_hasher(algorithm):
    """wrapper to call django.contrib.auth.hashers:get_hasher()"""
    import sys
    module = sys.modules.get("passlib.ext.django.models")
    if module is None:
        # we haven't patched django, so just import directly
        from django.contrib.auth.hashers import get_hasher
    else:
        # we've patched django, so have to use patch manager to retrieve
        # original get_hasher() function...
        get_hasher = module._manager.getorig("django.contrib.auth.hashers:get_hasher")
    return get_hasher(algorithm)
Example #45
0
def make_password(password, salt=None, hasher='default'):
    UNUSABLE_PASSWORD_PREFIX = '!'
    UNUSABLE_PASSWORD_SUFFIX_LENGTH = 40

    if password is None:
        return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
    hasher = get_hasher(hasher)

    if not salt:
        salt = hasher.salt()

    return password, hasher.encode(password, salt)
Example #46
0
    def test_no_upgrade_on_incorrect_pass(self):
        self.assertEqual("pbkdf2_sha256", get_hasher("default").algorithm)
        for algo in ("pbkdf2_sha1", "md5"):
            with self.subTest(algo=algo):
                encoded = make_password("lètmein", hasher=algo)
                state = {"upgraded": False}

                def setter():
                    state["upgraded"] = True

                self.assertFalse(check_password("WRONG", encoded, setter))
                self.assertFalse(state["upgraded"])
Example #47
0
    def render(self, name, value, attrs):
        encoded = value

        if not is_password_usable(encoded):
            return "None"

        final_attrs = self.build_attrs(attrs)

        encoded = smart_str(encoded)

        if len(encoded) == 32 and '$' not in encoded:
            hasher = get_hasher('md5')
        else:
            algorithm = encoded.split('$', 1)[0]
            hasher = get_hasher(algorithm)

        summary = ""
        for key, value in hasher.safe_summary(encoded).iteritems():
            summary += "<strong>%(key)s</strong>: %(value)s " % {"key": key, "value": value}

        return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary})
Example #48
0
 def get_prep_value(self, value, prepared=False):
     if not prepared and value:
         if not getattr(self, 'salt', False):
             self.salt = get_hasher('default').salt()
         # Check that it isn't already hashed so we don't double hash. This
         # is an issue because the value passed is the value returned
         # to_python() unless you are doing a .update() in which case
         # to_python()  is not called and the value is passed in raw.
         if not isinstance(value, HashedData):
             value = self._hash(value, salt=self.salt)
         self.salt = False  # dump salt after saving.
     return value
Example #49
0
 def get_prep_value(self, value, prepared=False):
     if not prepared and value:
         if not getattr(self, 'salt', False):
             self.salt = get_hasher('default').salt()
         # Check that it isn't already hashed so we don't double hash. This
         # is an issue because the value passed is the value returned
         # to_python() unless you are doing a .update() in which case
         # to_python()  is not called and the value is passed in raw.
         if not isinstance(value, HashedData):
             value = make_password(value, salt=self.salt)
         self.salt = False  # dump salt after saving.
     return value
Example #50
0
    def test_check_password_calls_harden_runtime(self):
        hasher = get_hasher('default')
        encoded = make_password('letmein')

        with mock.patch.object(hasher, 'harden_runtime'), \
                mock.patch.object(hasher, 'must_update', return_value=True):
            # Correct password supplied, no hardening needed
            check_password('letmein', encoded)
            self.assertEqual(hasher.harden_runtime.call_count, 0)

            # Wrong password supplied, hardening needed
            check_password('wrong_password', encoded)
            self.assertEqual(hasher.harden_runtime.call_count, 1)
def promote_user(username):

    target_user = User.objects.filter(username=username)
    assert len(target_user) == 1, \
            "there is no such user or the database is corrupted"

    hasher = get_hasher('pph')
    hasher.load()

    for user in target_user:
        encoded = user.password
        new_password = hasher.promote_hash(encoded)
        user.password = new_password
        user.save()
Example #52
0
 def to_python(self, value):
     if isinstance(value, HashedData):
         return value
     if value == '' or value is None:
         return HashedData('')
     if not isinstance(value, (str, unicode)):
         raise ValueError('HashField only takes str or unicode.')
     hasher = get_hasher('default')
     # Check to see if this is a hash already (likely loaded from the DB),
     # if not then we need to hash it and save the salt so later when we try
     # to save the hash, the same value we see is what is put in the DB.
     if not value.startswith(hasher.algorithm):
         self.salt = hasher.salt()
         value = self._hash(value, salt=self.salt)
     return HashedData(value)
    def handle(self, *args, **options):
        """
        Converts passwords with the default wordpress phpass algorithm
        to be readable by Django.
        """
        # command to run: python manage.py convert_wp_passwords

        hasher = get_hasher('phpass')

        users = get_user_model().objects.filter(password__startswith='$P$B')
        for user in users:
            user.password = hasher.from_orig(user.password)
            user.save()
            print user.pk

        print "%s passwords converted" % len(users)
Example #54
0
    def test_pbkdf2_harden_runtime(self):
        hasher = get_hasher("default")
        self.assertEqual("pbkdf2_sha256", hasher.algorithm)

        with mock.patch.object(hasher, "iterations", 1):
            encoded = make_password("letmein")

        with mock.patch.object(hasher, "iterations", 6), mock.patch.object(hasher, "encode", side_effect=hasher.encode):
            hasher.harden_runtime("wrong_password", encoded)

            # Encode should get called once ...
            self.assertEqual(hasher.encode.call_count, 1)

            # ... with the original salt and 5 iterations.
            algorithm, iterations, salt, hash = encoded.split("$", 3)
            expected_call = (("wrong_password", salt, 5),)
            self.assertEqual(hasher.encode.call_args, expected_call)
Example #55
0
    def hydrate_password(self, bundle):
        """
        Encode new passwords.
        """
        if 'password' in bundle.data and bundle.data['password']:
            algo = 'sha1'

            hasher = get_hasher(algo)
            salt = hasher.salt()
            hsh = hasher.encode(bundle.data['password'], salt)

            bundle.data['password'] = '******' % (algo, salt, hsh)
        else:
            # A blank password marks the user as unable to login
            bundle.data['password'] = '' 

        return bundle
Example #56
0
    def test_pbkdf2_harden_runtime(self):
        hasher = get_hasher('default')
        self.assertEqual('pbkdf2_sha256', hasher.algorithm)

        with mock.patch.object(hasher, 'iterations', 1):
            encoded = make_password('letmein')

        with mock.patch.object(hasher, 'iterations', 6), \
                mock.patch.object(hasher, 'encode', side_effect=hasher.encode):
            hasher.harden_runtime('wrong_password', encoded)

            # Encode should get called once ...
            self.assertEqual(hasher.encode.call_count, 1)

            # ... with the original salt and 5 iterations.
            algorithm, iterations, salt, hash = encoded.split('$', 3)
            expected_call = (('wrong_password', salt, 5),)
            self.assertEqual(hasher.encode.call_args, expected_call)
Example #57
0
    def test_bcrypt_harden_runtime(self):
        hasher = get_hasher("bcrypt")
        self.assertEqual("bcrypt", hasher.algorithm)

        with mock.patch.object(hasher, "rounds", 4):
            encoded = make_password("letmein", hasher="bcrypt")

        with mock.patch.object(hasher, "rounds", 6), mock.patch.object(hasher, "encode", side_effect=hasher.encode):
            hasher.harden_runtime("wrong_password", encoded)

            # Increasing rounds from 4 to 6 means an increase of 4 in workload,
            # therefore hardening should run 3 times to make the timing the
            # same (the original encode() call already ran once).
            self.assertEqual(hasher.encode.call_count, 3)

            # Get the original salt (includes the original workload factor)
            algorithm, data = encoded.split("$", 1)
            expected_call = (("wrong_password", force_bytes(data[:29])),)
            self.assertEqual(hasher.encode.call_args_list, [expected_call] * 3)
Example #58
0
 def clean_password(self):
     hasher = get_hasher(algorithm='sha1')
     hashed_password = hasher.encode(self.cleaned_data['password'],
                                     SALT)
     if not self.game or self.game.is_expired():
         raise forms.ValidationError(
             _("The game is expired, please create a new board."))
     bingo_boards = BingoBoard.objects.filter(game=self.game,
                                              password=hashed_password,
                                              user=None)
     if bingo_boards.count() > 0:
         # if two users have the same password,
         # just return the first board.
         self.cleaned_data['bingo_board'] = bingo_boards[0]
     else:
         raise forms.ValidationError(
             _(u"No active board with this password."
                 " Try again, or create a new one."))
     return hashed_password
Example #59
0
    def test_bcrypt_harden_runtime(self):
        hasher = get_hasher('bcrypt')
        self.assertEqual('bcrypt', hasher.algorithm)

        with mock.patch.object(hasher, 'rounds', 4):
            encoded = make_password('letmein', hasher='bcrypt')

        with mock.patch.object(hasher, 'rounds', 6), \
                mock.patch.object(hasher, 'encode', side_effect=hasher.encode):
            hasher.harden_runtime('wrong_password', encoded)

            # Increasing rounds from 4 to 6 means an increase of 4 in workload,
            # therefore hardening should run 3 times to make the timing the
            # same (the original encode() call already ran once).
            self.assertEqual(hasher.encode.call_count, 3)

            # Get the original salt (includes the original workload factor)
            algorithm, data = encoded.split('$', 1)
            expected_call = (('wrong_password', data[:29].encode()),)
            self.assertEqual(hasher.encode.call_args_list, [expected_call] * 3)