A self-hosted web applicationfor securely training and verifying your memory of passwords, PINs, or passphrases. PasswordTrainer helps you practice recalling sensitive credentials without storing them in plaintext, using strong cryptography and a simple, privacy-focused workflow.
- Secure password/PIN training: Practice recalling passwords or PINs without exposing them in plaintext.
- Zero plaintext storage: All secrets are stored encrypted and only checked in-memory.
- Argon2 hashing: Uses Argon2 for secure password and PIN verification.
- Data protection: Utilizes .NET Data Protection API for encrypting stored secrets.
- Rate limiting: Built-in protection against brute-force attacks on the
/checkendpoint using ASP.NET Core Rate Limiting Middleware. - Simple web UI: Minimal, responsive interface for quick password checks.
- Health check endpoint: For easy monitoring in production.
- .NET 10.0 SDK or later
- Docker (optional, for containerized deployment)
git clone https://github.com/mu88/PasswordTrainer.git
cd PasswordTrainerBefore running the app, you must initialize the secret files. This step creates the encrypted password store and required secret files.
dotnet run --project src/PasswordTrainer -- initialize-secretsYou will be prompted to enter:
- A new App-PIN (used to unlock the password store)
- The number of passwords to store
- Each password's ID/label and value
This creates the following files in the directories specified by the options:
pepper_secret(random secret)app_pin_hash(hashed PIN)secrets.json(encrypted password store)
docker run --rm -it \
-v $(pwd)/data:/data \
-v $(pwd)/secrets:/secrets \
-e Trainer__DataPath=/data \
-e Trainer__SecretsPath=/secrets \
ghcr.io/mu88/passwordtrainer:latest-chiseled initialize-secretsdotnet run --project src/PasswordTrainerdocker run --rm -p 8080:8080 \
-v $(pwd)/data:/data \
-v $(pwd)/secrets:/secrets \
-e Trainer__DataPath=/data \
-e Trainer__SecretsPath=/secrets \
ghcr.io/mu88/passwordtrainer:latest-chiseledThe web UI will be available at http://localhost:8080.
PasswordTrainer uses the Options pattern for configuration. The following environment variables (or appsettings) are required:
Trainer__DataPath: Directory for storing encrypted secrets and data protection keysTrainer__SecretsPath: Directory for storing secret files (pepper_secret,app_pin_hash)Trainer__PathBase: (Optional) Sets a custom base path for all endpoints (e.g.,/trainer). Must start with/and contain only alphanumeric characters, dashes, or slashes. If set, the web UI and API endpoints will be available under the specified path (e.g.,/trainer).
To protect against brute-force attacks, PasswordTrainer uses ASP.NET Core's Rate Limiting Middleware for the /check endpoint. You can configure the following parameters:
Trainer__RateLimitingPermitLimit: Maximum number of allowed requests per window (default: 15)Trainer__RateLimitingWindowMinutes: Time window in minutes for rate limiting (default: 5)
Example (in appsettings.json or as environment variables):
{
"Trainer": {
"RateLimitingPermitLimit": 15,
"RateLimitingWindowMinutes": 5
}
}This means a single IP address can only attempt to check credentials 15 times within a 5-minute window. Further requests will be blocked until the window resets.
{
"Trainer": {
"DataPath": "/data",
"SecretsPath": "/secrets",
"PathBase": "/trainer",
"RateLimitingPermitLimit": 15,
"RateLimitingWindowMinutes": 5
}
}You can also configure these via Docker -e flags.
- Open the web UI at
/trainer. - Enter your App-PIN, password ID/label, and password.
- The app will verify if the password matches the stored (encrypted) value for that ID.
- For issues, use the GitHub Issues page.
- See src/PasswordTrainer/PasswordTrainerOptions.cs for configuration details.
- Health check endpoint:
/trainer/healthz
Contributions are welcome! Please open issues before filing pull requests. See CONTRIBUTING.md if available. There is a Dev Container, too, see .devcontainer/devcontainer.json.
This project is licensed under the terms of the LICENSE.md file in this repository.