Keysoft is an offline-first password manager for Android, built with Expo, React Native, and TypeScript. It stores vault data locally and protects user content with authenticated encryption.
The application is designed around a local-only operating model: the PIN/master password is never persisted, vault data is encrypted at rest, and the app does not require a backend service to operate.
Keysoft works offline for vault management. Network access is limited to platform services such as Expo/EAS updates and is not used to sync, upload, or transmit vault contents, PINs, master passwords, or encryption keys.
| Area | Status |
|---|---|
| Platform focus | Android-first, iOS paused |
| App version | 2.0 |
| Android versionCode | 100 |
| Expo SDK | 55.0.23 |
| React Native | 0.83.6 |
| TypeScript | 5.9.3, strict mode |
| Test suite | 22 suites, 151 tests |
| Health check | expo-doctor 18/18 |
- Password vault with create, read, update, delete, search, pagination, and categories.
- Secure notes stored with the same vault encryption model.
- Local password generator backed by cryptographically secure randomness.
- Optional biometric unlock backed by SecureStore with device authentication.
- Local notifications for security reminders and backup prompts.
- Encrypted import/export workflow for user-managed backups.
- Italian and English localization with system-language detection.
- Automated i18n checks for Italian/English key parity, placeholder parity, and user-facing fallback regressions.
- Source-structure regression checks for lowercase directories and shared settings hook placement.
- Light and dark themes, Android-focused layout, and responsive test coverage.
Keysoft uses the KS1 envelope for vault data:
- AES-256-CBC for encryption.
- HMAC-SHA256 for integrity verification.
- Argon2id in EAS/native builds when available, PBKDF2 fallback in Expo Go or where required.
- Expo Go is a development workflow. Vaults created in Expo Go use PBKDF2 fallback metadata; use EAS/native builds for release-grade Argon2 validation.
- 64-character hex derived keys.
- CSPRNG-backed salts, IVs, IDs, and password generation.
- The vault key stays in memory by default. If biometrics are enabled, the vault key is stored in SecureStore with device authentication required and is updated or removed when the PIN changes.
- PIN setup and PIN changes reuse the vault key derived during verifier creation to avoid duplicate KDF work while preserving the configured Argon2/PBKDF2 cost.
Backup files use a password-encrypted payload format (KS1-PW1) with KDF metadata and authenticated KS1 ciphertext.
See Security Architecture for the full model, operational assumptions, and storage rules.
- Architecture
- Security Architecture
- Development Guide
- Release Guide
- Public Repository Checklist
- Pre-Build Security/UI Review
- Changelog
- Bun
- Node.js compatible with the Expo toolchain
- Expo Go installed on the Android device used for development
- Expo account access for EAS builds on expo.dev
- Expo CLI via
bunx expo
bun installStart the Expo development server for Expo Go:
bun run startOpen on Android with Expo Go:
bun run androidUse a tunnel when the phone cannot reach the local machine over LAN:
bun run start:tunnelRun web for development/testing:
bun run webBuild artifacts are produced on expo.dev through EAS:
bun run build:android:preview
bun run build:android:productionEAS builds upload the project to expo.dev. Start them only after the release checklist is complete and the upload has been explicitly approved.
Run the full local verification suite before shipping changes:
bun run typecheck
bun run lint
bun run test
bunx expo-doctor
bunx expo export --platform android --output-dir C:\tmp\keysoft-android-exportCurrent verified state:
bun run typecheck: passingbun run lint: passingbun run test: passing, 22 suites and 151 testsbunx expo-doctor: passing, 18/18 checksbunx expo export --platform android --output-dir C:\tmp\keysoft-android-export: passing
src/
components/ Shared UI components
contexts/ Application state providers
hooks/ Complex screen and behavior logic
settings/ Settings workflows extracted from SettingsScreen
(usePinManagement, useNotificationSettings,
useProfileForm, useExportImport)
locales/ i18n dictionaries (it.ts, en.ts) consumed by LanguageContext
models/ TypeScript domain models
navigation/ Navigation configuration (typed via NativeStackScreenProps)
screens/ User-facing screens
services/ Business, crypto, storage, auth, and utility services
utils/ Shared platform and security helpers (incl. withTimeout)
Path aliases (@/*, @components/*, @services/*, …) are configured in
tsconfig.json and babel.config.js for use in new code.
Keysoft is local-first. The user owns their vault data and is responsible for keeping backup files and the master password secure. The app cannot recover a lost master password because no server-side recovery material exists.
If Keysoft's local-first security work is useful to you, support continued development through GitHub Sponsors: github.com/sponsors/TheStreamCode.
This repository is source-available. See LICENSE for permitted use and restrictions.
Please do not open public issues for vulnerabilities. Follow SECURITY.md for private reporting guidance.
