Secure generation of salt for password hashing
- Usage of Python 3 for writing and executing Python code
- Usage of hashlib for cryptographic hashing operations
- Usage of random for generating random numbers or values
Non compliant code
# This will generate a salt of 2 characters length
salt = hashlib.sha256(str(random.getrandbits(16)).encode('utf-8')).hexdigest()[:2]
def insecure_hash_password(password, salt):
return hashlib.sha256((password + salt).encode('utf-8')).hexdigest()
In the above Python code, we have two functions
insecure_salt function is generating a salt. However, it is doing so in a very insecure way. It uses the
random.getrandbits(16) function to generate a random number, which it then hashes using SHA-256. The result is truncated to the first two characters. This results in a salt with very low entropy, as it can only have one of 256 possible values (16^2).
insecure_hash_password function hashes a given password with a salt. It concatenates the password and the salt, then hashes this string using SHA-256. However, due to the insecure way the salt is generated, an attacker with knowledge of this method could easily guess the salt and thus make it much easier to crack the password.
A secure salt should be unique and random, with sufficient length to prevent precomputation attacks. In this case, the salt is neither sufficiently random nor long enough, making it vulnerable to attacks.
- Increase the length of the salt. A longer salt makes it harder for an attacker to guess the password.
- Use a secure random number generator to create the salt. This ensures that the salt is unpredictable.
- Store the salt separately from the hashed password. This makes it harder for an attacker to guess the password even if they have access to the hashed password.
- Use a slow hash function like bcrypt, scrypt or Argon2. These functions are designed to be slow to compute, which makes brute force attacks more difficult.
from passlib.hash import bcrypt
# This will generate a salt of 16 bytes length
salt = os.urandom(16)
def secure_hash_password(password, salt):
# Use bcrypt to hash the password with the salt
hashed_password = bcrypt.using(salt=salt).hash(password)
The above code fixes the vulnerability in the following ways:
Increased Salt Length: The
secure_saltfunction now generates a salt of 16 bytes length. This is significantly longer than the previous 2 characters length, making it much harder for an attacker to guess the password.
Secure Random Number Generator: The
os.urandomfunction is used to generate the salt. This function generates random numbers from sources provided by the operating system, which are designed to be unpredictable.
Separate Salt Storage: The salt is now returned separately from the hashed password. This means that it can be stored separately, making it harder for an attacker to guess the password even if they have access to the hashed password.
Slow Hash Function: The
bcryptfunction from the
passliblibrary is used to hash the password. This function is designed to be slow to compute, which makes brute force attacks more difficult. The salt is passed to the
bcryptfunction using the
usingmethod, ensuring that it is used in the hashing process.