Aug 26 - Enhance security
CI / Python lint (flake8) (push) Has been cancelled
CI / Python syntax check (push) Has been cancelled
CI / Alembic migration chain (push) Has been cancelled
CI / JavaScript syntax check (push) Has been cancelled
CI / Build extension zip (push) Has been cancelled

This commit is contained in:
2026-08-26 10:37:00 -04:00
parent 0295fac3fa
commit 0304095e53
9 changed files with 502 additions and 112 deletions
+10
View File
@@ -39,6 +39,16 @@ class User(db.Model, UserMixin):
# The server never sees the recovery code — only the ciphertext of enc_key_salt.
recovery_enc_salt = db.Column(db.String(128), nullable=True)
recovery_iv = db.Column(db.String(64), nullable=True)
# recovery_verifier: 64 hex chars (256 bits), derived client-side from the
# recovery code ALONE:
# PBKDF2(recovery_code, "passkeeper-recovery-verifier:" + email, 200k, SHA-256)
# Used only as the HMAC key for the recovery challenge-response proof.
# It is deliberately independent of enc_key_salt: enc_key_salt doubles as the
# vault-key PBKDF2 salt and is handed to the client at login, so keying the
# proof with it let anyone holding the password forge a proof and pull the
# whole encrypted vault from /recovery/items without a second factor.
# NULL = legacy recovery code; the proof falls back to enc_key_salt.
recovery_verifier = db.Column(db.String(64), nullable=True)
# Brute-force lockout — incremented on every failed login attempt,
# reset to 0 on success. locked_until is set to now()+15min after
# MAX_FAILED_LOGINS consecutive failures.