hashlib

Updated March 13, 2026 · Modules
cryptography hashing security sha256 md5

The hashlib module provides secure hash functions for password storage, data integrity verification, and digital signatures. It includes implementations of MD5, SHA-1, SHA-256, SHA-512, and many other algorithms.

Syntax

import hashlib

# Create a hash object
h = hashlib.sha256()
h.update(b"data to hash")
digest = h.hexdigest()

Or using the one-shot API (Python 3.8+):

hashlib.sha256(b"data to hash").hexdigest()

Available Hash Algorithms

SHA-256

The most common choice for general-purpose hashing. Provides 256-bit output.

import hashlib

# One-shot API (Python 3.8+)
result = hashlib.sha256(b"hello world").hexdigest()
print(result)
# 94ee059335e587e501cc4bf83d831f5e077e7ec4aebedb208b4cd4e21d8e3917

# Using update for streaming
h = hashlib.sha256()
h.update(b"hello ")
h.update(b"world")
print(h.hexdigest())
# 94ee059335e587e501cc4bf83d831f5e077e7ec4aebedb208b4cd4e21d8e3917

# Binary digest (raw bytes)
print(hashlib.sha256(b"hello").digest())
# b'\x2c\x26\x93\x92...'

SHA-512

Provides 512-bit output. Slower than SHA-256 but more secure against collision attacks.

import hashlib

result = hashlib.sha512(b"hello world").hexdigest()
print(result)
# 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae5a71e4452e994e1b4b0361e52ca67867c54a8b3d64e9a2c1c6c7c8e4e52ca678

SHA-1

Deprecated for security purposes. Use SHA-256 or SHA-512 instead.

import hashlib
import warnings

# Still works but deprecated
result = hashlib.sha1(b"hello world").hexdigest()
print(result)
# 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed

MD5

Deprecated for security purposes. Use SHA-256 instead. Still useful for non-security purposes like quick checksums for file integrity.

import hashlib

result = hashlib.md5(b"hello world").hexdigest()
print(result)
# 5eb63bbbe01eeed093cb22bb8f5acdc3

Using hashlib.new()

Create a hash object with any available algorithm by name:

import hashlib

# blake2b - modern, fast, and cryptographically secure
h = hashlib.new("blake2b")
h.update(b"data")
print(h.hexdigest())
# 1a0e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e9f7e

# Check available algorithms
print(hashlib.algorithms_available)
# {'sha256', 'sha512', 'blake2b', 'blake2s', 'md5', ...}

Using hashlib.pbkdf2_hmac()

Derive a key from a password using PBKDF2 (Password-Based Key Derivation Function 2):

import hashlib
import os

password = b"my secure password"
salt = os.urandom(16)  # Random salt

# Key derivation with 100,000 iterations
key = hashlib.pbkdf2_hmac('sha256', password, salt, 100000)
print(key.hex())
# 3d2e1c0a7c1f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9

# Verify by re-computing with same salt
key2 = hashlib.pbkdf2_hmac('sha256', password, salt, 100000)
print(key == key2)
# True

Common Patterns

Password Hashing

Never store plain-text passwords. Always hash with a salt:

import hashlib
import secrets

def hash_password(password: str) -> tuple[str, str]:
    """Hash a password with a random salt."""
    salt = secrets.token_hex(16)
    pwd_bytes = password.encode('utf-8')
    salt_bytes = bytes.fromhex(salt)
    
    # Use many iterations for security
    hashed = hashlib.pbkdf2_hmac('sha256', pwd_bytes, salt_bytes, 100000)
    return hashed.hex(), salt

def verify_password(password: str, stored_hash: str, salt: str) -> bool:
    """Verify a password against a stored hash."""
    pwd_bytes = password.encode('utf-8')
    salt_bytes = bytes.fromhex(salt)
    new_hash = hashlib.pbkdf2_hmac('sha256', pwd_bytes, salt_bytes, 100000)
    return new_hash.hex() == stored_hash

# Usage
hashed, salt = hash_password("mypassword")
print(verify_password("mypassword", hashed, salt))  # True
print(verify_password("wrongpassword", hashed, salt))  # False

File Checksum

Verify file integrity by computing a hash:

import hashlib

def file_hash(filepath: str, algorithm: str = "sha256") -> str:
    """Compute hash of a file."""
    h = hashlib.new(algorithm)
    with open(filepath, "rb") as f:
        while chunk := f.read(8192):
            h.update(chunk)
    return h.hexdigest()

# Usage
# print(file_hash("large_file.zip"))

Constant-Time Comparison

Use secrets.compare_digest to compare hashes safely (prevents timing attacks):

import hashlib
import secrets

stored_hash = hashlib.sha256(b"password123").hexdigest()
input_hash = hashlib.sha256(b"password123").hexdigest()

# Safe comparison
if secrets.compare_digest(stored_hash, input_hash):
    print("Passwords match!")

Security Notes

  • SHA-1 and MD5 are deprecated for security. Use for checksums only.
  • SHA-256 is the minimum recommended for new applications.
  • PBKDF2 with 100,000+ iterations is recommended for password hashing.
  • bcrypt or argon2 are better choices for password storage than raw PBKDF2.
  • Always use a unique random salt for each password.

See Also