By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
(SHA-256, MD5 (deprecated), HMAC, and Salting)
Hashing is not encryption—it’s a one-way function that turns data into a fixed-size "fingerprint" (hash). In security, you’ll use it for: - Password storage (never store plaintext passwords—hash them!) - File integrity checks (e.g., verifying a downloaded ISO hasn’t been tampered with) - Digital signatures (proving a message hasn’t been altered) - API authentication (HMAC for request signing)
Real-world scenario: You’re a sysadmin inheriting a legacy web app. The database stores passwords in plaintext (? disaster waiting to happen). Your first task: migrate to hashed passwords with salts before the next breach. If you don’t, attackers who dump the database get every user’s password instantly.
Why this matters in production: - MD5 is broken (collisions found in seconds—never use it for security). - SHA-256 is the current standard for most use cases (but SHA-3 is emerging). - Salting prevents rainbow table attacks (precomputed hashes for common passwords). - HMAC adds a secret key to hashing, making it useful for API authentication.
482c811da5d5b4bc6d497ffa98491e38
python3 --version
openssl version
# Download a test file (e.g., Ubuntu ISO) wget https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso # Generate SHA-256 hash sha256sum ubuntu-22.04.3-desktop-amd64.iso
Expected output:
a1b2c3d4e5f6...ubuntu-22.04.3-desktop-amd64.iso
Why this matters: If the hash matches the one on Ubuntu’s website, the file hasn’t been tampered with.
# Generate a random salt (16 bytes = 32 hex chars) openssl rand -hex 16
Example output:
3a7b9c1d5e8f0a2b4c6d8e0f1a3b5c7d
Now, hash a password with the salt (using Python):
import hashlib password = "SuperSecret123" salt = "3a7b9c1d5e8f0a2b4c6d8e0f1a3b5c7d" # From openssl command above # Combine password + salt and hash with SHA-256 hashed_password = hashlib.sha256((password + salt).encode()).hexdigest() print(f"Salt: {salt}") print(f"Hashed password: {hashed_password}")
Salt: 3a7b9c1d5e8f0a2b4c6d8e0f1a3b5c7d Hashed password: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
Why this matters: Even if two users have the same password, their hashes will differ because of the unique salt.
def verify_password(input_password, stored_hash, salt): # Hash the input password with the stored salt new_hash = hashlib.sha256((input_password + salt).encode()).hexdigest() return new_hash == stored_hash # Test with correct password print(verify_password("SuperSecret123", "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8", "3a7b9c1d5e8f0a2b4c6d8e0f1a3b5c7d")) # Output: True # Test with wrong password print(verify_password("WrongPassword", "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8", "3a7b9c1d5e8f0a2b4c6d8e0f1a3b5c7d")) # Output: False
Why this matters: This is exactly how secure password storage works in production (e.g., Django, Flask, ASP.NET).
import hmac import hashlib # Secret key (should be stored securely, e.g., AWS Secrets Manager) secret_key = b"SuperSecretAPIKey123" # Message to sign (e.g., API request) message = b"user_id=123&action=delete" # Generate HMAC-SHA256 signature = hmac.new(secret_key, message, hashlib.sha256).hexdigest() print(f"HMAC-SHA256: {signature}")
HMAC-SHA256: 7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069
Why this matters: APIs like AWS S3, Stripe, and GitHub use HMAC to verify requests. Without the secret key, attackers can’t forge valid signatures.
users.salt
#-Good (constant-time comparison) if hmac.compare_digest(hash1, hash2): return True ```
SHA-256, HMAC-SHA256.
"What is the purpose of a salt?"
"To encrypt the password" ( hashing-encryption).
"Which is better for password storage: SHA-256 or bcrypt?"
SHA-256 (too fast for passwords).
"What does HMAC provide that SHA-256 alone does not?"
You’re given a database dump with unsalted MD5 password hashes. An attacker has a rainbow table. How do you migrate to SHA-256 with salts without forcing users to reset passwords?
# Example: Migrate an MD5 hash to SHA-256 with salt old_md5_hash = "5f4dcc3b5aa765d61d8327deb882cf99" # MD5("password") salt = "3a7b9c1d5e8f0a2b4c6d8e0f1a3b5c7d" # Random salt
# Re-hash the MD5 hash with salt (not the plaintext password!) new_sha256_hash = hashlib.sha256((old_md5_hash + salt).encode()).hexdigest() print(new_sha256_hash) ```3. Store the new hash and salt in the database.4. Update the login system to use SHA-256 with salts.
Why this works: - You never store plaintext passwords (even temporarily). - The MD5 hash acts as a "proxy" for the password during migration. - After migration, disable MD5 entirely.
sha256sum file.txt
echo -n "password" \| sha256sum
-n
md5sum file.txt
openssl rand -hex 16
echo -n "message" \| openssl dgst -sha256 -hmac "key"
bcrypt.hashpw(password.encode(), bcrypt.gensalt())
bcrypt.checkpw(password.encode(), stored_hash)
hashlib
hmac
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.