Beispiel #1
0
 def encode(self, password, salt):
     argon2 = self._load_library()
     data = argon2.low_level.hash_secret(
         force_bytes(password),
         force_bytes(salt),
         time_cost=self.time_cost,
         memory_cost=self.memory_cost,
         parallelism=self.parallelism,
         hash_len=argon2.DEFAULT_HASH_LENGTH,
         type=argon2.low_level.Type.I,
     )
     return self.algorithm + data.decode('ascii')
Beispiel #2
0
 def verify(self, password, encoded):
     argon2 = self._load_library()
     algorithm, rest = encoded.split('$', 1)
     assert algorithm == self.algorithm
     try:
         return argon2.low_level.verify_secret(
             force_bytes('$' + rest),
             force_bytes(password),
             type=argon2.low_level.Type.I,
         )
     except argon2.exceptions.VerificationError:
         return False
Beispiel #3
0
 def encode(self, password, salt):
     argon2 = self._load_library()
     data = argon2.low_level.hash_secret(
         force_bytes(password),
         force_bytes(salt),
         time_cost=self.time_cost,
         memory_cost=self.memory_cost,
         parallelism=self.parallelism,
         hash_len=argon2.DEFAULT_HASH_LENGTH,
         type=argon2.low_level.Type.I,
     )
     return self.algorithm + data.decode('ascii')
Beispiel #4
0
 def verify(self, password, encoded):
     argon2 = self._load_library()
     algorithm, rest = encoded.split('$', 1)
     assert algorithm == self.algorithm
     try:
         return argon2.low_level.verify_secret(
             force_bytes('$' + rest),
             force_bytes(password),
             type=argon2.low_level.Type.I,
         )
     except argon2.exceptions.VerificationError:
         return False
Beispiel #5
0
    def encode(self, password, salt):
        bcrypt = self._load_library()
        # Hash the password prior to using bcrypt to prevent password
        # truncation as described in #20138.
        if self.digest is not None:
            # Use binascii.hexlify() because a hex encoded bytestring is
            # Unicode on Python 3.
            password = binascii.hexlify(self.digest(force_bytes(password)).digest())
        else:
            password = force_bytes(password)

        data = bcrypt.hashpw(password, salt)
        return "%s$%s" % (self.algorithm, force_text(data))
Beispiel #6
0
    def pbkdf2(password, salt, iterations, dklen=0, digest=None):
        """
        Implements PBKDF2 as defined in RFC 2898, section 5.2

        HMAC+SHA256 is used as the default pseudo random function.

        As of 2014, 100,000 iterations was the recommended default which took
        100ms on a 2.7Ghz Intel i7 with an optimized implementation. This is
        probably the bare minimum for security given 1000 iterations was
        recommended in 2001. This code is very well optimized for CPython and
        is about five times slower than OpenSSL's implementation. Look in
        orun.contrib.auth.hashers for the present default, it is lower than
        the recommended 100,000 because of the performance difference between
        this and an optimized implementation.
        """
        assert iterations > 0
        if not digest:
            digest = hashlib.sha256
        password = force_bytes(password)
        salt = force_bytes(salt)
        hlen = digest().digest_size
        if not dklen:
            dklen = hlen
        if dklen > (2 ** 32 - 1) * hlen:
            raise OverflowError('dklen too big')
        l = -(-dklen // hlen)
        r = dklen - (l - 1) * hlen

        hex_format_string = "%%0%ix" % (hlen * 2)

        inner, outer = digest(), digest()
        if len(password) > inner.block_size:
            password = digest(password).digest()
        password += b'\x00' * (inner.block_size - len(password))
        inner.update(password.translate(hmac.trans_36))
        outer.update(password.translate(hmac.trans_5C))

        def F(i):
            u = salt + struct.pack(b'>I', i)
            result = 0
            for j in range(int(iterations)):
                dig1, dig2 = inner.copy(), outer.copy()
                dig1.update(u)
                dig2.update(dig1.digest())
                u = dig2.digest()
                result ^= _bin_to_long(u)
            return _long_to_bin(result, hex_format_string)

        T = [F(x) for x in range(1, l)]
        return b''.join(T) + F(l)[:r]
Beispiel #7
0
    def encode(self, password, salt):
        bcrypt = self._load_library()
        # Hash the password prior to using bcrypt to prevent password
        # truncation as described in #20138.
        if self.digest is not None:
            # Use binascii.hexlify() because a hex encoded bytestring is
            # Unicode on Python 3.
            password = binascii.hexlify(
                self.digest(force_bytes(password)).digest())
        else:
            password = force_bytes(password)

        data = bcrypt.hashpw(password, salt)
        return "%s$%s" % (self.algorithm, force_text(data))
Beispiel #8
0
    def pbkdf2(password, salt, iterations, dklen=0, digest=None):
        """
        Implements PBKDF2 with the same API as Orun's existing
        implementation, using the stdlib.

        This is used in Python 2.7.8+ and 3.4+.
        """
        if digest is None:
            digest = hashlib.sha256
        if not dklen:
            dklen = None
        password = force_bytes(password)
        salt = force_bytes(salt)
        return hashlib.pbkdf2_hmac(
            digest().name, password, salt, iterations, dklen)
Beispiel #9
0
 def save(self, domain_override=None,
          subject_template_name='registration/password_reset_subject.txt',
          email_template_name='registration/password_reset_email.html',
          use_https=False, token_generator=default_token_generator,
          from_email=None, request=None, html_email_template_name=None,
          extra_email_context=None):
     """
     Generate a one-use only link for resetting password and send it to the
     user.
     """
     email = self.cleaned_data["email"]
     for user in self.get_users(email):
         if not domain_override:
             current_site = get_current_site(request)
             site_name = current_site.name
             domain = current_site.domain
         else:
             site_name = domain = domain_override
         context = {
             'email': email,
             'domain': domain,
             'site_name': site_name,
             'uid': urlsafe_base64_encode(force_bytes(user.pk)),
             'user': user,
             'token': token_generator.make_token(user),
             'protocol': 'https' if use_https else 'http',
             **(extra_email_context or {}),
         }
         self.send_mail(
             subject_template_name, email_template_name, context, from_email,
             email, html_email_template_name=html_email_template_name,
         )
Beispiel #10
0
def truncate_name(name, length=None, hash_len=4):
    """Shortens a string to a repeatable mangled version with the given length.
    """
    if length is None or len(name) <= length:
        return name

    hsh = hashlib.md5(force_bytes(name)).hexdigest()[:hash_len]
    return '%s%s' % (name[:length - hash_len], hsh)
Beispiel #11
0
 def harden_runtime(self, password, encoded):
     _, data = encoded.split('$', 1)
     salt = data[:29]  # Length of the salt in bcrypt.
     rounds = data.split('$')[2]
     # work factor is logarithmic, adding one doubles the load.
     diff = 2**(self.rounds - int(rounds)) - 1
     while diff > 0:
         self.encode(password, force_bytes(salt))
         diff -= 1
Beispiel #12
0
 def harden_runtime(self, password, encoded):
     _, data = encoded.split('$', 1)
     salt = data[:29]  # Length of the salt in bcrypt.
     rounds = data.split('$')[2]
     # work factor is logarithmic, adding one doubles the load.
     diff = 2**(self.rounds - int(rounds)) - 1
     while diff > 0:
         self.encode(password, force_bytes(salt))
         diff -= 1
Beispiel #13
0
 def _digest(cls, *args):
     """
     Generates a 32-bit digest of a set of arguments that can be used to
     shorten identifying names.
     """
     h = hashlib.md5()
     for arg in args:
         h.update(force_bytes(arg))
     return h.hexdigest()[:8]
Beispiel #14
0
def urlsafe_base64_decode(s):
    """
    Decodes a base64 encoded string, adding back any trailing equal signs that
    might have been stripped.
    """
    s = force_bytes(s)
    try:
        return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'='))
    except (LookupError, BinasciiError) as e:
        raise ValueError(e)
Beispiel #15
0
def salted_hmac(key_salt, value, secret=None):
    """
    Returns the HMAC-SHA1 of 'value', using a key generated from key_salt and a
    secret (which defaults to settings.SECRET_KEY).

    A different key_salt should be passed in for every application of HMAC.
    """
    if secret is None:
        secret = settings.SECRET_KEY

    key_salt = force_bytes(key_salt)
    secret = force_bytes(secret)

    # We need to generate a derived key from our base key.  We can do this by
    # passing the key_salt and our base key through a pseudo-random function and
    # SHA1 works nicely.
    key = hashlib.sha1(key_salt + secret).digest()

    # If len(key_salt + secret) > sha_constructor().block_size, the above
    # line is redundant and could be replaced by key = key_salt + secret, since
    # the hmac module does the same thing for keys longer than the block size.
    # However, we need to ensure that we *always* do this.
    return hmac.new(key, msg=force_bytes(value), digestmod=hashlib.sha1)
Beispiel #16
0
 def _create_index_name(self, model, column_names, suffix="", prefix=""):
     """
     Generates a unique name for an index/unique constraint.
     """
     # If there is just one column in the index, use a default algorithm from Orun
     if len(column_names) == 1 and not suffix:
         name = model._meta.table_name
         name = name.replace('"', '')
         if '.' in name:
             name = name.split('.')[1]
         ix_name = column_names[0]
         #ix_name = self._digest(column_names[0])
         if name[-1] == '"':
             name = '%s%s_%s"' % (prefix, name[:-1], ix_name)
         else:
             name = '%s%s_%s' % (prefix, name, ix_name)
         return truncate_name(name, 127)
     # Else generate the name for the index using a different algorithm
     table_name = model._meta.db_table.replace('"', '').replace('.', '_')
     index_unique_name = '_%s' % self._digest(table_name, *column_names)
     max_length = self.connection.conn_info.ops.max_name_length() or 200
     # If the index name is too long, truncate it
     index_name = ('%s%s_%s%s%s' % (
         prefix, table_name, column_names[0], index_unique_name, suffix,
     )).replace('"', '').replace('.', '_')
     if len(index_name) > max_length:
         part = ('_%s%s%s' % (column_names[0], index_unique_name, suffix))
         index_name = '%s%s' % (table_name[:(max_length - len(part))], part)
     # It shouldn't start with an underscore (Oracle hates this)
     if index_name[0] == "_":
         index_name = index_name[1:]
     # If it's STILL too long, just hash it down
     if len(index_name) > max_length:
         index_name = hashlib.md5(force_bytes(index_name)).hexdigest()[:max_length]
     # It can't start with a number on Oracle, so prepend D if we need to
     if index_name[0].isdigit():
         index_name = "D%s" % index_name[:-1]
     return index_name
Beispiel #17
0
 def verify(self, password, encoded):
     algorithm, data = encoded.split('$', 1)
     assert algorithm == self.algorithm
     encoded_2 = self.encode(password, force_bytes(data))
     return constant_time_compare(encoded, encoded_2)
Beispiel #18
0
 def convert_binaryfield_value(self, value, expression, connection, context):
     if isinstance(value, Database.LOB):
         value = force_bytes(value.read())
     return value
Beispiel #19
0
 def encode(self, password, salt):
     assert salt == ''
     return hashlib.md5(force_bytes(password)).hexdigest()
Beispiel #20
0
 def encode(self, password, salt):
     assert salt == ''
     hash = hashlib.sha1(force_bytes(password)).hexdigest()
     return 'sha1$$%s' % hash
Beispiel #21
0
 def verify(self, password, encoded):
     algorithm, data = encoded.split('$', 1)
     assert algorithm == self.algorithm
     encoded_2 = self.encode(password, force_bytes(data))
     return constant_time_compare(encoded, encoded_2)
Beispiel #22
0
 def encode(self, password, salt):
     assert password is not None
     assert salt and '$' not in salt
     hash = hashlib.md5(force_bytes(salt + password)).hexdigest()
     return "%s$%s$%s" % (self.algorithm, salt, hash)
Beispiel #23
0
 def encode(self, password, salt):
     assert salt == ''
     hash = hashlib.sha1(force_bytes(password)).hexdigest()
     return 'sha1$$%s' % hash
Beispiel #24
0
 def encode(self, password, salt):
     assert salt == ''
     return hashlib.md5(force_bytes(password)).hexdigest()
Beispiel #25
0
 def constant_time_compare(val1, val2):
     return hmac.compare_digest(force_bytes(val1), force_bytes(val2))
Beispiel #26
0
 def encode(self, password, salt):
     assert password is not None
     assert salt and '$' not in salt
     hash = hashlib.md5(force_bytes(salt + password)).hexdigest()
     return "%s$%s$%s" % (self.algorithm, salt, hash)