Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/utils/crypto.py: 84%
30 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""
2Django's standard crypto functions and utilities.
3"""
4import hashlib
5import hmac
6import secrets
8from django.conf import settings
9from django.utils.encoding import force_bytes
12class InvalidAlgorithm(ValueError):
13 """Algorithm is not supported by hashlib."""
15 pass
18def salted_hmac(key_salt, value, secret=None, *, algorithm="sha1"):
19 """
20 Return the HMAC of 'value', using a key generated from key_salt and a
21 secret (which defaults to settings.SECRET_KEY). Default algorithm is SHA1,
22 but any algorithm name supported by hashlib can be passed.
24 A different key_salt should be passed in for every application of HMAC.
25 """
26 if secret is None: 26 ↛ 27line 26 didn't jump to line 27, because the condition on line 26 was never true
27 secret = settings.SECRET_KEY
29 key_salt = force_bytes(key_salt)
30 secret = force_bytes(secret)
31 try:
32 hasher = getattr(hashlib, algorithm)
33 except AttributeError as e:
34 raise InvalidAlgorithm(
35 "%r is not an algorithm accepted by the hashlib module." % algorithm
36 ) from e
37 # We need to generate a derived key from our base key. We can do this by
38 # passing the key_salt and our base key through a pseudo-random function.
39 key = hasher(key_salt + secret).digest()
40 # If len(key_salt + secret) > block size of the hash algorithm, the above
41 # line is redundant and could be replaced by key = key_salt + secret, since
42 # the hmac module does the same thing for keys longer than the block size.
43 # However, we need to ensure that we *always* do this.
44 return hmac.new(key, msg=force_bytes(value), digestmod=hasher)
47RANDOM_STRING_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
50def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
51 """
52 Return a securely generated random string.
54 The bit length of the returned value can be calculated with the formula:
55 log_2(len(allowed_chars)^length)
57 For example, with default `allowed_chars` (26+26+10), this gives:
58 * length: 12, bit length =~ 71 bits
59 * length: 22, bit length =~ 131 bits
60 """
61 return "".join(secrets.choice(allowed_chars) for i in range(length))
64def constant_time_compare(val1, val2):
65 """Return True if the two strings are equal, False otherwise."""
66 return secrets.compare_digest(force_bytes(val1), force_bytes(val2))
69def pbkdf2(password, salt, iterations, dklen=0, digest=None):
70 """Return the hash of password using pbkdf2."""
71 if digest is None: 71 ↛ 72line 71 didn't jump to line 72, because the condition on line 71 was never true
72 digest = hashlib.sha256
73 dklen = dklen or None
74 password = force_bytes(password)
75 salt = force_bytes(salt)
76 return hashlib.pbkdf2_hmac(digest().name, password, salt, iterations, dklen)