Standalone password hashing utilities for any Python web framework.
Works with StarSpring, FastAPI, Flask, Django, or any Python project.
Choose the algorithm you need:
# BCrypt (recommended — default)
pip install starspring-security[bcrypt]
# Argon2 (modern, memory-hard)
pip install starspring-security[argon2]
# Both
pip install starspring-security[all]from starspring_security import BCryptPasswordEncoder
encoder = BCryptPasswordEncoder()
# Hash a password
hashed = encoder.encode("my_secret_password")
# Verify a password
encoder.matches("my_secret_password", hashed) # True
encoder.matches("wrong_password", hashed) # FalseBCrypt is slow by design — making brute-force attacks expensive. Automatically salts every password.
from starspring_security import BCryptPasswordEncoder
encoder = BCryptPasswordEncoder() # Default: rounds=12
encoder = BCryptPasswordEncoder(rounds=14) # Stronger (slower)
hashed = encoder.encode("password")
encoder.matches("password", hashed) # TrueWinner of the Password Hashing Competition (2015). More resistant to GPU attacks than BCrypt due to memory hardness.
from starspring_security import Argon2PasswordEncoder
encoder = Argon2PasswordEncoder()
hashed = encoder.encode("password")
encoder.matches("password", hashed) # True
# Custom parameters
encoder = Argon2PasswordEncoder(time_cost=3, memory_cost=65536, parallelism=2)SHA-256 is not recommended for passwords — it is too fast and vulnerable to brute-force attacks. Use BCrypt or Argon2 instead.
Included for legacy/migration purposes only. Raises a DeprecationWarning.
from starspring_security import Sha256PasswordEncoder
encoder = Sha256PasswordEncoder() # ⚠️ DeprecationWarning raised
hashed = encoder.encode("password")
encoder.matches("password", hashed) # Truefrom starspring import Service, Transactional
from starspring_security import BCryptPasswordEncoder
encoder = BCryptPasswordEncoder()
@Service
class UserService:
def __init__(self, user_repo):
self.user_repo = user_repo
@Transactional
async def register(self, username: str, password: str):
user = User(username=username, password=encoder.encode(password))
return await self.user_repo.save(user)
async def authenticate(self, username: str, password: str):
user = await self.user_repo.find_by_username(username)
if user and encoder.matches(password, user.password):
return user
return Nonefrom fastapi import FastAPI, HTTPException
from starspring_security import BCryptPasswordEncoder
app = FastAPI()
encoder = BCryptPasswordEncoder()
@app.post("/register")
def register(username: str, password: str):
hashed = encoder.encode(password)
# save to DB...
@app.post("/login")
def login(username: str, password: str):
user = get_user(username) # from DB
if not encoder.matches(password, user.password):
raise HTTPException(status_code=401, detail="Invalid credentials")from flask import Flask
from starspring_security import BCryptPasswordEncoder
app = Flask(__name__)
encoder = BCryptPasswordEncoder()
@app.route("/register", methods=["POST"])
def register():
hashed = encoder.encode(request.form["password"])
# save to DB...
@app.route("/login", methods=["POST"])
def login():
user = get_user(request.form["username"])
if not encoder.matches(request.form["password"], user.password):
return "Invalid credentials", 401from starspring_security import BCryptPasswordEncoder
encoder = BCryptPasswordEncoder()
# In your view or service
def create_user(username, password):
hashed = encoder.encode(password)
User.objects.create(username=username, password=hashed)
def authenticate(username, password):
user = User.objects.get(username=username)
return encoder.matches(password, user.password)| BCrypt | Argon2 | SHA-256 | |
|---|---|---|---|
| Recommended | ✅ Yes | ✅ Yes | ❌ No |
| Auto-salted | ✅ Yes | ✅ Yes | ✅ Yes (in this lib) |
| Brute-force resistant | ✅ Yes | ✅ Yes | ❌ No |
| GPU resistant | ✅ Yes | ❌ No | |
| Extra dependency | bcrypt |
argon2-cffi |
None |
MIT — see LICENSE