pypi / legacy_passwords.py

import base64
import hashlib

import passlib.exc as exc
import passlib.utils.handlers as uh

from passlib.registry import get_crypt_handler
from passlib.utils import to_unicode
from passlib.utils.compat import uascii_to_str


passlib_bcrypt = get_crypt_handler("bcrypt")


class bcrypt_sha1(uh.StaticHandler):

    name = "bcrypt_sha1"
    _hash_prefix = u"$bcrypt_sha1$"

    def _calc_checksum(self, secret):
        # Hash the secret with sha1 first
        secret = hashlib.sha1(secret).hexdigest()

        # Hash it with bcrypt
        return passlib_bcrypt.encrypt(secret)

    def to_string(self):
        assert self.checksum is not None
        return uascii_to_str(self._hash_prefix + base64.b64encode(self.checksum))

    @classmethod
    def from_string(cls, hash, **context):
        # default from_string() which strips optional prefix,
        # and passes rest unchanged as checksum value.
        hash = to_unicode(hash, "ascii", "hash")
        hash = cls._norm_hash(hash)
        # could enable this for extra strictness
        ##pat = cls._hash_regex
        ##if pat and pat.match(hash) is None:
        ##    raise ValueError("not a valid %s hash" % (cls.name,))
        prefix = cls._hash_prefix
        if prefix:
            if hash.startswith(prefix):
                hash = hash[len(prefix):]
            else:
                raise exc.InvalidHashError(cls)

        # Decode the base64 stored actual hash
        hash = unicode(base64.b64decode(hash))

        return cls(checksum=hash, **context)

    @classmethod
    def verify(cls, secret, hash, **context):
        # NOTE: classes with multiple checksum encodings should either
        # override this method, or ensure that from_string() / _norm_checksum()
        # ensures .checksum always uses a single canonical representation.
        uh.validate_secret(secret)
        self = cls.from_string(hash, **context)
        chk = self.checksum
        if chk is None:
            raise exc.MissingDigestError(cls)

        # Actually use the verify from passlib_bcrypt after hashing the secret
        #   with sha1
        secret = hashlib.sha1(secret).hexdigest()
        return passlib_bcrypt.verify(secret, chk)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.