Secure Password Hashing in Python
In the realm of web security and data protection, storing user passwords in plain text is a critical vulnerability. This challenge focuses on implementing a secure password hashing mechanism in Python, a fundamental practice for protecting sensitive user credentials. You will learn to use a robust hashing algorithm to transform passwords into a secure, one-way representation, making it significantly harder for attackers to compromise user accounts even if your database is breached.
Problem Description
Your task is to implement a Python function that securely hashes a given password. This involves using a strong, industry-standard hashing algorithm that includes salting to prevent common attacks like rainbow table lookups.
Requirements:
- Hashing Algorithm: You must use a modern, secure password hashing algorithm. The
argon2-cffilibrary is highly recommended for its state-of-the-art security features. If you prefer,bcryptis also an acceptable alternative. Avoid older, less secure algorithms like MD5 or SHA-1. - Salting: The hashing process must automatically generate and incorporate a unique salt for each password. This salt should be stored along with the hash.
- Verification: You need to implement a function to verify if a given password matches a stored hash (which includes the salt).
- Function Signatures:
hash_password(password: str) -> str: This function should take a plain-text password and return a securely hashed string representation.verify_password(password: str, hashed_password: str) -> bool: This function should take a plain-text password and the stored hashed password (including the salt) and returnTrueif they match,Falseotherwise.
Expected Behavior:
hash_passwordshould always produce a different hash output for the same password if called multiple times (due to unique salting).verify_passwordshould returnTruewhen given the original password and its corresponding hash.verify_passwordshould returnFalsewhen given an incorrect password and its corresponding hash.verify_passwordshould correctly handle different hash formats generated by the chosen library.
Edge Cases to Consider:
- Empty passwords.
- Passwords with special characters, whitespace, or unusual encoding.
- The output of
hash_passwordmust be a single string that can be stored and later used for verification.
Examples
Example 1:
Input:
password = "mysecretpassword123"
Output:
# The output will be a string representing the salt and hash, e.g.:
# $argon2id$v=19$m=65536,t=3,p=4$yourgeneratedsalt$yourgeneratedhash
# (Actual output format depends on the library used and specific parameters)
Explanation:
The `hash_password` function takes the plain-text password and generates a unique salt, then hashes the password with the salt. The output is a single string containing both the salt and the hash, encoded in a format recognizable by the verification function.
Example 2:
Input:
password = "mysecretpassword123"
hashed_password = "$argon2id$v=19$m=65536,t=3,p=4$yourgeneratedsalt$yourgeneratedhash" # (This would be the output from Example 1)
Output:
True
Explanation:
The `verify_password` function extracts the salt from the `hashed_password` string, hashes the provided `password` with that extracted salt, and compares the resulting hash with the hash stored within `hashed_password`. Since the password and salt match, it returns `True`.
Example 3:
Input:
password = "wrongpassword"
hashed_password = "$argon2id$v=19$m=65536,t=3,p=4$yourgeneratedsalt$yourgeneratedhash" # (Hash from Example 1)
Output:
False
Explanation:
Even though `hashed_password` contains a valid hash, the `verify_password` function correctly identifies that the provided `password` ("wrongpassword") does not match the original password that generated the hash, returning `False`.
Constraints
- The input
passwordwill be a string. - The output of
hash_passwordmust be a single string. - The
hashed_passwordinput toverify_passwordwill be a string generated byhash_passwordfrom the same chosen library. - The hashing process should be computationally intensive enough to deter brute-force attacks, but fast enough for reasonable user experience during login. The default or recommended parameters of
argon2-cffiorbcryptare generally suitable.
Notes
- Library Choice: For this challenge, it is strongly recommended to use the
argon2-cffilibrary. You can install it using pip:pip install argon2-cffi. If you choosebcrypt, install it withpip install bcrypt. - Parameters: Password hashing algorithms have various tunable parameters (e.g., memory cost, time cost, parallelism). For this challenge, you can use the library's default or recommended parameters. Understanding these parameters is crucial for production systems, but for this exercise, focusing on correct implementation with salting and verification is key.
- Storage: The output of
hash_passwordis what you would store in your database for each user. Never store plain-text passwords. - Security Best Practices: Always keep your hashing libraries updated to benefit from the latest security research and improvements.