Get a Pentest and security assessment of your IT network.

Cyber Security

Verify Password Hash

TL;DR

This guide shows you how to check if a user’s entered password matches a stored salted hash without needing the username. It focuses on secure comparison techniques to prevent timing attacks and other vulnerabilities.

Steps

  1. Understand the Setup
    • You have a database storing user passwords as salted hashes. This means each password was combined with a unique ‘salt’ before being hashed (e.g., using bcrypt, Argon2).
    • You need to verify if a provided password matches the stored hash for a specific user. Crucially, you *don’t* have the username available at this stage – only the hash and salt.
  2. Retrieve Salt and Hash
  3. Fetch the salt and corresponding hash from your database. The method depends on how you store them (e.g., separate columns, JSON object). For example, using SQL:

    SELECT password_hash, salt FROM users WHERE user_id = 123;
  4. Hash the Entered Password
  5. Use the same hashing algorithm (e.g., bcrypt) and the retrieved salt to hash the password entered by the user.

    import bcrypt
    
    salt = "your_retrieved_salt"
    hashed_password = bcrypt.hashpw(entered_password.encode('utf-8'), salt.encode('utf-8'))
  6. Securely Compare the Hashes
  7. This is the most important step! Never directly compare strings using ==. Timing attacks can reveal information about the hash.

    • Use a constant-time comparison function provided by your hashing library. These functions are designed to take the same amount of time regardless of whether the hashes match or not.
    import bcrypt
    
    hashed_password = "your_hashed_password"
    entered_password_hash = "your_newly_hashed_password"
    
    if bcrypt.checkpw(entered_password_hash.encode('utf-8'), hashed_password.encode('utf-8')):
        print("Password matches!")
    else:
        print("Password does not match.")

    Important: The bcrypt.checkpw() function handles the secure comparison for you.

  8. Argon2 Example (Alternative)
  9. If using Argon2, the process is similar:

    import argon2
    
    ph = argon2.PasswordHasher()
    try:
        argon2.verify(hashed_password, entered_password)
        print("Password matches!")
    except argon2.exceptions.VerifyMismatchError:
        print("Password does not match.")

    Important: Argon2’s verify() function performs the secure comparison.

  10. Handle Errors and Edge Cases
    • Check for null or empty salt/hash values in your database.
    • Ensure you are using a strong hashing algorithm (bcrypt, Argon2) with appropriate parameters (work factor/memory cost).
    • Implement proper error handling to prevent information leaks.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation