Get a Pentest and security assessment of your IT network.

Cyber Security

HMAC Password Leak Risk

TL;DR

Yes, HMAC can leak your password if implemented incorrectly. The main risk comes from using a weak or predictable key, or not salting the input properly before hashing. Always use strong, randomly generated keys and incorporate a unique salt for each password.

Understanding HMAC

HMAC (Hash-based Message Authentication Code) is used to verify both the data integrity and authenticity of a message. It involves a cryptographic hash function and a secret key. It’s commonly used in password storage, but it’s not a magic bullet.

Why HMAC Can Leak Passwords

HMAC itself isn’t flawed; the problem lies in how it’s used. Here’s how leaks can happen:

  1. Weak Key: If your secret key is weak (e.g., a common word, short length), attackers can brute-force it.
  2. Predictable Key: Using a predictable key generation method means an attacker could guess the key.
  3. No Salt: Without a salt, identical passwords will produce the same HMAC hash. Attackers can use precomputed tables (rainbow tables) to quickly crack these hashes.
  4. Insufficient Hashing Rounds: A fast hashing algorithm with few rounds is vulnerable to brute-force attacks.

How to Protect Against Password Leaks

Follow these steps to secure your password storage using HMAC:

  1. Generate a Strong Key: Use a cryptographically secure random number generator to create a long, unpredictable key. Avoid hardcoding keys directly into your code.
    # Python example (using secrets module)
    import secrets
    key = secrets.token_hex(32) # Generates a 64-character hex string (32 bytes)
    print(key)
  2. Use a Unique Salt for Each Password: A salt is random data added to the password before hashing. This makes rainbow table attacks much harder.
    import os
    salt = os.urandom(16) # Generates 16 bytes of random data
    print(salt.hex())
  3. Combine Salt and Password Before Hashing: Concatenate the salt with the password before passing it to the HMAC function.
    import hmac
    hash_object = hmac.new(key.encode('utf-8'), (salt + password).encode('utf-8'), digestmod='sha256')
    hmac_hash = hash_object.hexdigest()
    print(hmac_hash)
  4. Store the Salt Alongside the Hash: You need to store both the HMAC hash and the salt used to generate it. This is essential for verifying passwords later.
  5. Use a Slow Hashing Algorithm: Choose a hashing algorithm designed to be slow (e.g., SHA-256, SHA-512) and increase the number of iterations/rounds. Libraries like bcrypt or Argon2 handle this automatically.
    # Example using bcrypt in Python
    import bcrypt
    hashed_password = bcrypt.hashpw((salt + password).encode('utf-8'), bcrypt.gensalt())
    print(hashed_password)
  6. Regularly Re-Hash Passwords: If your hashing algorithm is compromised, re-hashing passwords with a stronger method will protect your users.

Password Verification

When a user enters their password:

  1. Retrieve the stored HMAC hash and salt for that user.
  2. Concatenate the retrieved salt with the entered password.
  3. Calculate the HMAC hash using the same key and algorithm as before.
  4. Compare the calculated hash with the stored hash. If they match, the password is correct.
    # Python example for verification
    import hmac
    stored_hash = "..."
    tored_salt = "..."
    user_password = "..."
    hash_object = hmac.new(key.encode('utf-8'), (stored_salt + user_password).encode('utf-8'), digestmod='sha256')
    calculated_hash = hash_object.hexdigest()
    if calculated_hash == stored_hash:
      print("Password verified!")
    else:
      print("Incorrect password.")
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