
Research
/Security News
9 Malicious NuGet Packages Deliver Time-Delayed Destructive Payloads
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.
hash-forge
Advanced tools
Hash Forge is a lightweight Python library designed to simplify the process of hashing and verifying data using a variety of secure hashing algorithms.
Hash Forge is a lightweight Python library designed to simplify the process of hashing and verifying data using a variety of secure hashing algorithms.
Hash Forge is a flexible and secure hash management tool that supports multiple hashing algorithms. This tool allows you to hash and verify data using popular hash algorithms, making it easy to integrate into projects where password hashing or data integrity is essential.
hash_async(), verify_async(), and batch processing.AlgorithmType for better IDE support.pip install hash-forge
Hash Forge provides optional dependencies for specific hashing algorithms. To install these, use:
bcrypt support:
pip install "hash-forge[bcrypt]"
Argon2 support:
pip install "hash-forge[argon2]"
Whirlpool and RIPEMD-160 support:
pip install "hash-forge[crypto]"
Blake3 support:
pip install "hash-forge[blake3]"
from hash_forge import HashManager
# Create a HashManager with Argon2 (recommended)
hash_manager = HashManager.from_algorithms("argon2")
# Hash a password
hashed = hash_manager.hash("my_secure_password")
# Verify a password
is_valid = hash_manager.verify("my_secure_password", hashed)
print(is_valid) # True
# Check if rehashing is needed
needs_update = hash_manager.needs_rehash(hashed)
from hash_forge import HashManager, AlgorithmType
from hash_forge.hashers import PBKDF2Sha256Hasher
# Initialize HashManager with PBKDF2Hasher
hash_manager = HashManager(PBKDF2Sha256Hasher())
# Hash a string
hashed_value = hash_manager.hash("my_secure_password")
# Verify the string against the hashed value
is_valid = hash_manager.verify("my_secure_password", hashed_value)
print(is_valid) # Outputs: True
# Check if the hash needs rehashing
needs_rehash = hash_manager.needs_rehash(hashed_value)
print(needs_rehash) # Outputs: False
Check out the examples/ directory for more practical examples:
For simple hashing without creating a HashManager instance:
from hash_forge import HashManager, AlgorithmType
# Quick hash with default algorithm (PBKDF2-SHA256)
hashed = HashManager.quick_hash("my_password")
# Quick hash with specific algorithm (with IDE autocomplete!)
algorithm: AlgorithmType = "argon2"
hashed = HashManager.quick_hash("my_password", algorithm=algorithm)
# Quick hash with algorithm-specific parameters
hashed = HashManager.quick_hash("my_password", algorithm="pbkdf2_sha256", iterations=200_000)
hashed = HashManager.quick_hash("my_password", algorithm="bcrypt", rounds=14)
hashed = HashManager.quick_hash("my_password", algorithm="argon2", time_cost=4)
Create HashManager instances using algorithm names:
from hash_forge import HashManager, AlgorithmType
# Create HashManager from algorithm names
hash_manager = HashManager.from_algorithms("pbkdf2_sha256", "argon2", "bcrypt")
# With type safety
algorithms: list[AlgorithmType] = ["pbkdf2_sha256", "bcrypt_sha256"]
hash_manager = HashManager.from_algorithms(*algorithms)
# Note: from_algorithms() creates hashers with default parameters
# For custom parameters, create hashers individually
hash_manager = HashManager.from_algorithms("pbkdf2_sha256", "bcrypt", "argon2")
Note: The first hasher provided during initialization of
HashManagerwill be the preferred hasher used for hashing operations, though any available hasher can be used for verification.
Currently supported algorithms with their AlgorithmType identifiers:
| Algorithm | Identifier | Security Level | Notes |
|---|---|---|---|
| PBKDF2-SHA256 | "pbkdf2_sha256" | High | Default, 150K iterations minimum |
| PBKDF2-SHA1 | "pbkdf2_sha1" | Medium | Legacy support |
| bcrypt | "bcrypt" | High | 12 rounds minimum |
| bcrypt-SHA256 | "bcrypt_sha256" | High | With SHA256 pre-hashing |
| Argon2 | "argon2" | Very High | Memory-hard function |
| Scrypt | "scrypt" | High | Memory-hard function |
| Blake2 | "blake2" | High | Fast cryptographic hash |
| Blake3 | "blake3" | Very High | Latest Blake variant |
| Whirlpool | "whirlpool" | Medium | 512-bit hash |
| RIPEMD-160 | "ripemd160" | Medium | 160-bit hash |
Different algorithms support different parameters. Use quick_hash() for algorithm-specific customization:
from hash_forge import HashManager
# PBKDF2 algorithms
HashManager.quick_hash("password", algorithm="pbkdf2_sha256", iterations=200_000, salt_length=16)
HashManager.quick_hash("password", algorithm="pbkdf2_sha1", iterations=150_000)
# BCrypt algorithms
HashManager.quick_hash("password", algorithm="bcrypt", rounds=14)
HashManager.quick_hash("password", algorithm="bcrypt_sha256", rounds=12)
# Argon2
HashManager.quick_hash("password", algorithm="argon2", time_cost=4, memory_cost=65536, parallelism=1)
# Scrypt
HashManager.quick_hash("password", algorithm="scrypt", n=32768, r=8, p=1)
# Blake2 (with optional key)
HashManager.quick_hash("password", algorithm="blake2", key="secret_key")
# Blake3 (with optional key)
HashManager.quick_hash("password", algorithm="blake3", key="secret_key")
# Other algorithms (use defaults)
HashManager.quick_hash("password", algorithm="whirlpool")
HashManager.quick_hash("password", algorithm="ripemd160")
For complete control over parameters, initialize HashManager with individual hasher instances:
from hash_forge import HashManager
from hash_forge.hashers import (
Argon2Hasher,
BCryptSha256Hasher,
Blake2Hasher,
PBKDF2Sha256Hasher,
Ripemd160Hasher,
ScryptHasher,
WhirlpoolHasher,
Blake3Hasher
)
hash_manager = HashManager(
PBKDF2Sha256Hasher(iterations=200_000), # Higher iterations
BCryptSha256Hasher(rounds=14), # Higher rounds
Argon2Hasher(time_cost=4), # Custom parameters
ScryptHasher(),
Ripemd160Hasher(),
Blake2Hasher('MySecretKey'),
WhirlpoolHasher(),
Blake3Hasher()
)
Use the verify method to compare a string with its hashed counterpart:
is_valid = hash_manager.verify("my_secure_password", hashed_value)
You can check if a hash needs to be rehashed (e.g., if the hashing algorithm parameters are outdated):
needs_rehash = hash_manager.needs_rehash(hashed_value)
Hash Forge provides full async/await support for non-blocking operations. All synchronous methods have async equivalents that run in a thread pool executor to avoid blocking the event loop.
import asyncio
from hash_forge import HashManager
async def main():
hash_manager = HashManager.from_algorithms("argon2")
# Async hashing - runs synchronous hash in thread pool
hashed = await hash_manager.hash_async("my_password")
print(f"Hashed: {hashed}")
# Async verification - non-blocking verification
is_valid = await hash_manager.verify_async("my_password", hashed)
print(f"Valid: {is_valid}") # True
# Async rehash check
needs_rehash = await hash_manager.needs_rehash_async(hashed)
print(f"Needs rehash: {needs_rehash}") # False
asyncio.run(main())
Process multiple passwords concurrently for better performance:
import asyncio
from hash_forge import HashManager
async def batch_example():
hash_manager = HashManager.from_algorithms("pbkdf2_sha256")
# Hash multiple passwords concurrently
passwords = ["user1_pass", "user2_pass", "user3_pass", "user4_pass"]
hashes = await hash_manager.hash_many_async(passwords)
# hashes is a list with the same order as passwords
for password, hash_value in zip(passwords, hashes):
print(f"{password} -> {hash_value[:50]}...")
# Verify multiple password-hash pairs concurrently
pairs = [
("user1_pass", hashes[0]),
("user2_pass", hashes[1]),
("wrong_password", hashes[2]), # This will be False
]
results = await hash_manager.verify_many_async(pairs)
print(f"Results: {results}") # [True, True, False]
asyncio.run(batch_example())
Perfect for async web frameworks like FastAPI, Sanic, or aiohttp:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from hash_forge import HashManager
app = FastAPI()
hash_manager = HashManager.from_algorithms("argon2")
class LoginRequest(BaseModel):
username: str
password: str
@app.post("/register")
async def register(request: LoginRequest):
# Non-blocking password hashing
hashed = await hash_manager.hash_async(request.password)
# Save user with hashed password to database
return {"username": request.username, "password_hash": hashed}
@app.post("/login")
async def login(request: LoginRequest):
# Fetch user from database (simulated)
stored_hash = get_user_hash(request.username)
# Non-blocking password verification
is_valid = await hash_manager.verify_async(request.password, stored_hash)
if not is_valid:
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"message": "Login successful"}
The async methods are particularly useful when:
import asyncio
import time
from hash_forge import HashManager
async def performance_comparison():
hash_manager = HashManager.from_algorithms("argon2")
passwords = [f"password_{i}" for i in range(10)]
# Sequential (blocking)
start = time.time()
hashes_sync = [hash_manager.hash(pwd) for pwd in passwords]
sync_time = time.time() - start
# Concurrent (non-blocking)
start = time.time()
hashes_async = await hash_manager.hash_many_async(passwords)
async_time = time.time() - start
print(f"Sequential: {sync_time:.2f}s")
print(f"Concurrent: {async_time:.2f}s")
print(f"Speedup: {sync_time/async_time:.2f}x")
asyncio.run(performance_comparison())
Load configuration from environment variables, JSON files, or programmatically:
from hash_forge import HashManager
from hash_forge.config import HashForgeConfig
# From environment variables
# export HASH_FORGE_PBKDF2_ITERATIONS=200000
# export HASH_FORGE_BCRYPT_ROUNDS=14
config = HashForgeConfig.from_env()
# From JSON file
config = HashForgeConfig.from_json("config.json")
# Programmatically
config = HashForgeConfig(
pbkdf2_iterations=200_000,
bcrypt_rounds=14,
argon2_time_cost=4
)
# Create HashManager with config
hash_manager = HashManager.from_config(config, "pbkdf2_sha256", "bcrypt")
# Save config
config.to_json("hash_config.json")
Create HashManager instances with a fluent, chainable API:
from hash_forge import HashManager
# Use builder pattern for elegant configuration
hash_manager = (
HashManager.builder()
.with_algorithm("argon2", time_cost=4)
.with_algorithm("bcrypt", rounds=14)
.with_algorithm("pbkdf2_sha256", iterations=200_000)
.with_preferred("argon2") # Set preferred hasher
.build()
)
# Mix pre-configured hashers with algorithms
from hash_forge.hashers import PBKDF2Sha256Hasher
custom_hasher = PBKDF2Sha256Hasher(iterations=300_000)
hash_manager = (
HashManager.builder()
.with_hasher(custom_hasher)
.with_algorithm("bcrypt")
.build()
)
Hash Forge v3.0.0 represents a major architectural overhaul with significant performance improvements and new features while maintaining backward compatibility for the public API.
core/, config/, utils/, hashers/)hash_many_async() and verify_many_async()hash_async(), verify_async(), needs_rehash_async()AlgorithmType literals for IDE autocompleteWith async batch operations, v3.0.0 achieves significant speedups:
Hash Forge provides full async/await support for non-blocking operations. All synchronous methods have async equivalents that run in a thread pool executor to avoid blocking the event loop.
import asyncio
from hash_forge import HashManager
async def main():
hash_manager = HashManager.from_algorithms("argon2")
# Async hashing - runs synchronous hash in thread pool
hashed = await hash_manager.hash_async("my_password")
print(f"Hashed: {hashed}")
# Async verification - non-blocking verification
is_valid = await hash_manager.verify_async("my_password", hashed)
print(f"Valid: {is_valid}") # True
# Async rehash check
needs_rehash = await hash_manager.needs_rehash_async(hashed)
print(f"Needs rehash: {needs_rehash}") # False
asyncio.run(main())
Process multiple passwords concurrently for better performance:
import asyncio
from hash_forge import HashManager
async def batch_example():
hash_manager = HashManager.from_algorithms("pbkdf2_sha256")
# Hash multiple passwords concurrently
passwords = ["user1_pass", "user2_pass", "user3_pass", "user4_pass"]
hashes = await hash_manager.hash_many_async(passwords)
# hashes is a list with the same order as passwords
for password, hash_value in zip(passwords, hashes):
print(f"{password} -> {hash_value[:50]}...")
# Verify multiple password-hash pairs concurrently
pairs = [
("user1_pass", hashes[0]),
("user2_pass", hashes[1]),
("wrong_password", hashes[2]), # This will be False
]
results = await hash_manager.verify_many_async(pairs)
print(f"Results: {results}") # [True, True, False]
asyncio.run(batch_example())
Perfect for async web frameworks like FastAPI, Sanic, or aiohttp:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from hash_forge import HashManager
app = FastAPI()
hash_manager = HashManager.from_algorithms("argon2")
class LoginRequest(BaseModel):
username: str
password: str
@app.post("/register")
async def register(request: LoginRequest):
# Non-blocking password hashing
hashed = await hash_manager.hash_async(request.password)
# Save user with hashed password to database
return {"username": request.username, "password_hash": hashed}
@app.post("/login")
async def login(request: LoginRequest):
# Fetch user from database (simulated)
stored_hash = get_user_hash(request.username)
# Non-blocking password verification
is_valid = await hash_manager.verify_async(request.password, stored_hash)
if not is_valid:
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"message": "Login successful"}
The async methods are particularly useful when:
import asyncio
import time
from hash_forge import HashManager
async def performance_comparison():
hash_manager = HashManager.from_algorithms("argon2")
passwords = [f"password_{i}" for i in range(10)]
# Sequential (blocking)
start = time.time()
hashes_sync = [hash_manager.hash(pwd) for pwd in passwords]
sync_time = time.time() - start
# Concurrent (non-blocking)
start = time.time()
hashes_async = await hash_manager.hash_many_async(passwords)
async_time = time.time() - start
print(f"Sequential: {sync_time:.2f}s")
print(f"Concurrent: {async_time:.2f}s")
print(f"Speedup: {sync_time/async_time:.2f}x")
asyncio.run(performance_comparison())
Load configuration from environment variables, JSON files, or programmatically:
from hash_forge import HashManager
from hash_forge.config import HashForgeConfig
# From environment variables
# export HASH_FORGE_PBKDF2_ITERATIONS=200000
# export HASH_FORGE_BCRYPT_ROUNDS=14
config = HashForgeConfig.from_env()
# From JSON file
config = HashForgeConfig.from_json("config.json")
# Programmatically
config = HashForgeConfig(
pbkdf2_iterations=200_000,
bcrypt_rounds=14,
argon2_time_cost=4
)
# Create HashManager with config
hash_manager = HashManager.from_config(config, "pbkdf2_sha256", "bcrypt")
# Save config
config.to_json("hash_config.json")
Create HashManager instances with a fluent, chainable API:
from hash_forge import HashManager
# Use builder pattern for elegant configuration
hash_manager = (
HashManager.builder()
.with_algorithm("argon2", time_cost=4)
.with_algorithm("bcrypt", rounds=14)
.with_algorithm("pbkdf2_sha256", iterations=200_000)
.with_preferred("argon2") # Set preferred hasher
.build()
)
# Mix pre-configured hashers with algorithms
from hash_forge.hashers import PBKDF2Sha256Hasher
custom_hasher = PBKDF2Sha256Hasher(iterations=300_000)
hash_manager = (
HashManager.builder()
.with_hasher(custom_hasher)
.with_algorithm("bcrypt")
.build()
)
Hash Forge v3.0.0 represents a major architectural overhaul with significant performance improvements and new features while maintaining backward compatibility for the public API.
core/, config/, utils/, hashers/)hash_many_async() and verify_many_async()hash_async(), verify_async(), needs_rehash_async()AlgorithmType literals for IDE autocompleteWith async batch operations, v3.0.0 achieves significant speedups:
AlgorithmType literal for IDE autocomplete and error detectionHasherFactoryquick_hash() and from_algorithms() for simpler usageInvalidHasherError, UnsupportedAlgorithmError)AlgorithmType usageBefore v2.1.0:
# Manual hasher imports and creation
from hash_forge.hashers.pbkdf2_hasher import PBKDF2Sha256Hasher
hasher = PBKDF2Sha256Hasher(iterations=150000)
hash_manager = HashManager(hasher)
v2.1.0: v2.1.0:
# Simplified with factory pattern and type safety
from hash_forge import HashManager, AlgorithmType
algorithm: AlgorithmType = "pbkdf2_sha256" # IDE autocomplete!
hash_manager = HashManager.from_algorithms(algorithm)
# or with custom parameters
hashed = HashManager.quick_hash("password", algorithm=algorithm, iterations=200_000)
v3.0.0:
# Complete overhaul with builder, config, and async support
from hash_forge import HashManager
from hash_forge.config import HashForgeConfig
# Builder pattern with fluent API
hash_manager = (
HashManager.builder()
.with_algorithm("argon2", time_cost=4, memory_cost=65536)
.with_algorithm("bcrypt", rounds=14)
.with_preferred("argon2")
.build()
)
# Config management from JSON/env
config = HashForgeConfig.from_json("config.json")
hash_manager = HashManager.from_config(config, "argon2", "bcrypt")
# Async operations for non-blocking performance
import asyncio
async def main():
hashes = await hash_manager.hash_many_async(["pass1", "pass2", "pass3"])
# 3-5x faster than sequential hashing!
asyncio.run(main())
The public API remains backward compatible, but internal imports have changed:
✅ No changes needed (backward compatible):
from hash_forge import HashManager, AlgorithmType
from hash_forge.hashers import PBKDF2Sha256Hasher, BCryptHasher
hash_manager = HashManager.from_algorithms("pbkdf2_sha256")
hashed = hash_manager.hash("password")
⚠️ Update if using internal modules (rare):
# v2.x (deprecated)
from hash_forge.protocols import HasherProtocol
from hash_forge.factory import HasherFactory
# v3.0.0 (new paths)
from hash_forge.core.protocols import HasherProtocol
from hash_forge.core.factory import HasherFactory
hash_forge/
├── __init__.py # Public API
├── types.py # Type definitions (AlgorithmType)
├── exceptions.py # Exception classes
│
├── core/ # Core functionality (internal)
│ ├── manager.py # HashManager implementation
│ ├── builder.py # Builder pattern
│ ├── factory.py # Hasher factory
│ ├── protocols.py # Protocol definitions
│ └── base_hasher.py # Template base class
│
├── config/ # Configuration (internal)
│ ├── settings.py # Default parameters
│ ├── constants.py # Constants
│ └── logging.py # Logging configuration
│
├── hashers/ # Algorithm implementations
│ ├── pbkdf2_hasher.py
│ ├── bcrypt_hasher.py
│ ├── argon2_hasher.py
│ └── ...
│
└── utils/ # Utilities (internal)
└── helpers.py
Contributions are welcome! Please read our Contributing Guide for details on:
For security best practices and to report vulnerabilities, please see our Security Policy.
Recommended algorithms for password hashing:
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
Hash Forge is a lightweight Python library designed to simplify the process of hashing and verifying data using a variety of secure hashing algorithms.
We found that hash-forge demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.