Skip to content
Zeyu Zhao edited this page May 24, 2026 · 10 revisions

Mechanism

This page describes the high-level mechanism of Password-Manager v11.08.

The source code is the final authority. This page is meant to explain the design, not to replace code review.

Architecture

Password-Manager is split into two parts:

src/frontend/
src/backend/

The frontend is static HTML/CSS/JavaScript.

The backend is a PHP REST API.

Typical deployment:

Frontend: https://pm.example.com/
Backend:  https://api.example.com/passwordmanager/backend/

The frontend calls the backend through apiBaseUrl configured in:

src/frontend/config.js

The backend trusts only the configured frontend origin from:

src/backend/function/config.php

using:

$FRONTEND_URL = 'https://pm.example.com/';

Client-side encryption

Saved account data is encrypted and decrypted in the browser.

The backend stores encrypted strings. It should not receive the raw saved account passwords.

Current high-level crypto features include:

  • client-side AES-256 encryption
  • client-side PBKDF2 with SHA-512 or SHA3-512 depending on context
  • server-side PBKDF2 + SHA3-512 for authentication-related hashing
  • WebCrypto-based client-side cryptographic operations in modern versions

Because encryption is client-side, losing the login password can make data unrecoverable.

Login password

The login password is used by the browser to derive keys for decrypting saved data.

The server authenticates the user using derived authentication material, not by storing the raw login password.

If the login password is changed, the browser has to re-encrypt stored data. This can take time. Generate a new backup after each login password change.

Salts

v11.08 separates salts between frontend and backend config.

Frontend client-side salts:

src/frontend/config.js
globalSalt1: "...",
globalSalt2: "...",

Backend server-side salt:

src/backend/function/config.php
$GLOBAL_SALT_3 = '...';

Do not change these after data has been created.

For upgrades, copy old salt values exactly into the new split config files.

Backend storage

The backend stores data in MySQL/MariaDB.

The database contains encrypted entry data, authentication metadata, login history, trusted-device/PIN data, file data, and other metadata depending on enabled features.

The backend does not need the raw saved passwords to store or return entries.

Files

Files are encrypted in the browser before upload.

Only small files are supported. Treat file names and metadata as potentially revealing information even though file content is encrypted.

Backups include file data only when the Include Files option is selected.

PIN authentication

PIN login is a convenience feature for trusted devices.

It is designed so that a short PIN can unlock access on a device that has already been trusted. It is not a replacement for the master login password.

PIN login is disabled after repeated failed attempts. Trusted devices can be reviewed and disabled from:

Settings -> Account Activity

Master account TOTP 2FA

v11.08 uses TOTP-based 2FA for the Password-Manager master account.

E-mail based 2FA has been removed.

TOTP protects login against password-only compromise. Store the shown TOTP secret safely when enabling 2FA.

Important: master account TOTP metadata is authentication metadata. It is not the same as client-side encrypted saved-entry data.

Entry-level MFA/TOTP

Password-Manager can also store MFA/TOTP setup data for individual saved accounts.

Example: storing the TOTP secret for a GitHub account saved inside Password-Manager.

This entry-level MFA/TOTP data is part of the saved entry and is handled with the entry data in the browser.

Frontend integrity and deployment

Older versions documented a client-side source-file integrity check using separate check files.

v11.08 instead separates static frontend and backend deployment. The security goal is to serve the frontend JavaScript from a highly trusted static source that an attacker cannot modify, even if the backend server is compromised.

Recommended practices:

  • deploy the frontend to a locked-down static host
  • protect the static-hosting account with strong password and 2FA
  • deploy only release code
  • avoid unreviewed plugins
  • use HTTPS
  • do not add wildcard CORS headers

CORS and sessions

The backend should accept browser requests only from the configured frontend origin.

Do not configure:

Access-Control-Allow-Origin: *

The frontend/backend split also means frontend code should not rely on backend-domain cookies alone. Current frontend code sends session information through the configured API flow.

Backup and recovery

Backup generation happens in the browser.

Recovery also happens in the browser and does not require backend configuration.

A backup can be recovered with:

  • the backup file
  • the login password that was active when the backup was generated
  • a compatible recovery page

CSV and RAW exports from recovery should be treated as sensitive plaintext-equivalent data.

Safety summary

Password-Manager helps protect saved passwords from a passive database leak because saved entries are encrypted client-side.

It does not protect against every possible compromise. Important risks include:

  • malicious frontend JavaScript
  • compromised static frontend hosting account
  • compromised browser or device
  • weak login password
  • weak PIN on a trusted device
  • leaked CSV or RAW export
  • leaked recovery backup plus leaked login password

Use strong passwords, trusted frontend hosting, HTTPS, TOTP 2FA, safe backups, and careful device hygiene.

Clone this wiki locally