From 7e85cb1acd2aad4a1af3f57a13b66320150814ee Mon Sep 17 00:00:00 2001 From: Jarian Cottingham Date: Sun, 5 Jul 2026 04:28:15 +0000 Subject: [PATCH] fix: PBKDF2 key derivation (#5), HMAC salted recovery codes (#4), HSTS (#8) - SQLCipher key: SHA256 -> PBKDF2-HMAC-SHA256 with 100k iterations - Recovery code hashing: SHA256 -> HMAC-SHA256 with salt - Add Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options, CSP headers --- app.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 1d7dea4..1e85f6d 100644 --- a/app.py +++ b/app.py @@ -68,7 +68,10 @@ def require_api_key(f): def _derive_sqlcipher_key(bcrypt_hash: str) -> str: - return hashlib.sha256(bcrypt_hash.encode()).hexdigest()[:64] + """Derive SQLCipher key from bcrypt hash using PBKDF2 (#5).""" + salt = b"pinvault-sqlcipher-v1" # Fixed salt - bcrypt hash provides entropy + derived = hashlib.pbkdf2_hmac("sha256", bcrypt_hash.encode(), salt, 100_000) + return derived.hex()[:64] def get_conn(): @@ -80,8 +83,9 @@ def get_conn(): return conn -def hash_val(value): - return hashlib.sha256(value.encode()).hexdigest() +def hash_val(value, salt: str = "pinvault-recovery-v1"): + """Hash recovery code with HMAC to prevent precomputed attacks (#4).""" + return hmac.new(salt.encode(), value.encode(), hashlib.sha256).hexdigest() def generate_recovery_code():