Built because I got tired of paying $48/year just to autofill a password.
Most password managers lock their best features behind a subscription - cross-device sync, secure notes, TOTP codes, and even basic export often require a premium plan. 1Key exists to give you all of that, for free, forever, with no account required and no server ever involved.
| Vault Home | All Items | Credential Detail |
![]() |
![]() |
![]() |
| Edit Credential | 2FA / TOTP Codes | Settings |
![]() |
![]() |
![]() |
Every major password manager today requires you to:
- Create an account - your vault identity lives on someone else's server
- Trust their encryption - you have no way to verify how they actually store your data
- Pay for the features that matter - TOTP codes, secure export, and device sync are almost always premium
- Accept telemetry - usage analytics, crash reporting, and "improvement data" collection are on by default
1Key takes a different position: your passwords are yours. They live on your device, encrypted by a key only you hold, and they never move unless you explicitly export them.
- Store credentials with title, username, password, URL, notes, and custom fields
- Tag-based organisation with custom categories
- Favourites tab for frequently used accounts
- Full-text search across all fields
Most apps make you switch between a password manager and a separate authenticator. 1Key stores both in the same credential entry. Scan a QR code once, and your TOTP codes live alongside the password they protect - no app switching.
- Scan setup QR codes with the built-in camera scanner
- Live 30-second countdown with automatic code refresh
- One-tap copy to clipboard
Point your camera at a printed password, a screen showing credentials, or a physical token card, and 1Key extracts the text using on-device ML Kit OCR - no image is uploaded. The recognised text is pre-filled into the credential form for you to review and save. Everything runs locally on the device.
- Export your vault as an encrypted
.1keyfile (AES-256-GCM with Argon2id key derivation, timestamp and vault-version bound into the auth tag) or plain CSV/JSON - Encrypted exports require your master password to restore - no password, no access
- Import from 1Key backups or directly from other password managers
Supported import sources:
| App | Format |
|---|---|
| Google Passwords | CSV |
| LastPass | CSV |
| KeePassXC / KeePassDX / KeePass 2 | XML export (with 2FA and passkeys), KeePassXC .passkey files, CSV |
| Proton Authenticator | JSON export without password (2FA codes) |
| Safari / iCloud Keychain | CSV |
| 1Password | CSV |
| Dashlane | CSV |
| NordPass | CSV |
The importer auto-detects format and column headers - no manual mapping required. Duplicate credentials are detected and skipped.
- Master password - always available as the primary fallback
- Biometric - fingerprint or face unlock backed by hardware-secure key; requires master-password confirmation to enable
- PIN - 6-digit PIN for quick access; resets to master password if removed
- Background auto-lock - locks when the app moves to the background. Options: Immediate (default), 30 seconds, 1 minute, 5 minutes
- Inactivity auto-lock - locks when the app is in the foreground but idle. Options: Never, 30 seconds, 1 minute, 5 minutes (default), 15 minutes
- Periodic master-password recheck - optionally require master password every 48 hours / 3 days / 1 week / 3 weeks even when biometric or PIN is enabled
- Tiered attempt limiting - 3, 5, and 10 wrong attempts on master password or PIN trigger 30-second, 5-minute, and 1-hour cooldowns respectively. Counters survive process kills.
A quick at-a-glance comparison against five of the most popular password managers.
| 1Password | Bitwarden | Dashlane | LastPass | Proton Pass | 1Key | |
|---|---|---|---|---|---|---|
| Cost | $47.88/yr (no free tier) | Free; Premium $19.80/yr | ❌ $59.88/yr (free plan ended Sept 2025) | Free (1 device type); Premium $36/yr | Free; Plus $23.88/yr | ✅ Free, all features |
| Account signup required | ❌ Yes - email + verify | ❌ Yes - email + verify | ❌ Yes - email + verify | ❌ Yes - email + verify | ❌ Yes - Proton account | ✅ No - install and go |
| Hacked / compromised / leaked | No major incident known | ❌ May 2026: encrypted vaults of <20 personal-plan accounts stolen via device-registration 2FA brute-force (disclosed June 2026) 2 | ❌ 2022: backup DB stolen via two-stage employee laptop compromise; customer names, emails, phone numbers, and vault URLs all left unencrypted; 1.6M UK users hit; £1.2M (~$1.5M) ICO fine Dec 2025 3 | No major incident known | ✅ None - no server to breach | |
| INTERNET permission not required | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Vault stored on vendor servers | E2EE | E2EE | E2EE | ✅ Local only | ||
| Account metadata held off-device | Email, billing, devices | Email, devices | Email/username, devices, Proton account linkage across services | ✅ None | ||
| Telemetry / analytics | Opt-in | Opt-out (no in-app toggle; Google Analytics opt-out tool only) | Opt-out | Opt-out | Opt-out | ✅ None - no INTERNET |
| Multi-device sync | ✅ Real-time | ✅ Real-time | ✅ Real-time | ✅ Real-time | ✅ MP-unlock encrypted backup to user-chosen folder | |
| Sync without trusting a vendor server | ❌ 1Password servers | ❌ Dashlane servers | ❌ LastPass servers | ❌ Proton servers | ✅ User picks the folder: local, USB, Drive, Dropbox, or NAS (Network Attached Storage) | |
| Built-in TOTP / 2FA codes | ✅ | ❌ Premium only | ✅ | ❌ Enterprise / Identity only | ✅ | ✅ |
| PIN code unlock | ✅ | ✅ | ✅ | ✅ | ✅ | |
| OCR (camera scan) | ❌ TOTP QR only (no card / doc OCR) | ✅ cards (iOS 2026.5.0+) | ✅ cards | ✅ credentials (Smart Scanner, May 2026) | ❌ | ✅ logins, cards, notes & custom fields |
| Markdown in notes | ✅ post-save render 4 | ❌ plain text only 5 | ❌ plain text only 6 | ❌ plain text only 7 | ❌ plain text only (open UserVoice request) 8 | ✅ live-preview edit + view-mode render + helper bar (user can also disable it in Settings) |
| Categories | ✅ | ✅ Folders | ✅ | ✅ Folders | ✅ Vaults | ✅ |
| Encrypted local backup file | ❌ all exports plaintext 9 | ✅ JSON, password-encrypted | ✅ Dashlane export | ❌ CSV export only | ✅ | ✅ V5 envelope (Secret-Key-aware, V1-V4 still restorable) |
| Recycle bin (soft delete) | ✅ Recently Deleted (30 days) + Archive (hide, indefinite) | ✅ Trash | ❌ delete is immediate | ✅ 30-day | ✅ Trash | ✅ default on (user can toggle off in Settings) |
| KDF | PBKDF2-650k + Secret Key 10 | PBKDF2-600k default; Argon2id (m=64 MiB, t=3, p=4) opt-in 11 | Argon2d (m=32 MiB, t=3, p=2) 12 | PBKDF2-600k (was 100,100 pre-breach) 13 | bcrypt (cost not disclosed) 14 | Argon2id (m=64 MiB, t=3, p=1) + 128-bit Secret Key (enabled by default, opt-out supported); configurable up to m=256 MiB, t=16 15 |
| Verifier brute-forceable from leaked file | ✅ Not possible - 128-bit Secret Key required off-device | If cloud breached | ❌ Yes - proven in 2026 breach for ~20 accounts | ❌ Yes - proven in 2022 breach for old-iteration vaults | If cloud breached | ✅ Not possible - hardware Keystore-bound (TEE / StrongBox) |
| Open source | ❌ Closed | ✅ Client + server | ✅ Open source - GPL-3.0 |
Further reading on password-manager security: even local-only managers can have attack surface. The KeePass 2.x memory-leak CVE disclosed in May 2023 let an attacker extract the master password in cleartext from KeePass application memory on an already-compromised device. 1Key mitigates the same threat by holding the derived vault key in hardware-backed Android Keystore so it never sits in the app's heap. See https://www.secureworld.io/industry-news/keepass-security-flaw-password
For a full technical and strategic overview, see the 1Key white paper - cryptographic architecture, threat model, and a frank statement of what the project does and doesn't defend against.
1Key uses the same core primitives the major cloud vendors rely on - authenticated encryption (AES-256-GCM, as in 1Password and Proton Pass) and end-to-end-encrypted vault material - and goes further on key derivation by defaulting to memory-hard Argon2id (which Bitwarden offers only as opt-in, while 1Password still uses PBKDF2 and Proton Pass uses bcrypt). On top of that baseline, 1Key adds local-only hardening tailored to the Android threat model: the vault key never leaves the device, the master-password verifier is held in Keystore-backed EncryptedSharedPreferences (so a stolen DB file alone cannot be brute-forced offline), and Room columns are encrypted at rest with HKDF-derived per-field subkeys. 1Key also adopts 1Password Secret Key model: a 128-bit random value mixed into key derivation, default-on for new vaults, with opt-out at vault creation and full enable/disable/rotate controls in Settings > Security > Secret Key. This is not stronger crypto than well-funded competitors - but for users who don't want a server in the loop, it removes the off-device auth blob entirely, and the Secret Key gives offline backups the same 128-bit entropy floor 1Password has used for years.
| Encryption property | 1Password | Bitwarden | Proton Pass | 1Key |
|---|---|---|---|---|
| Password KDF (default) | PBKDF2-SHA256 650k iter + 128-bit Secret Key (~128 bits of extra entropy no KDF can match) | PBKDF2 600k (Argon2id 64MiB / t=3 / p=4 opt-in) | bcrypt (cost factor not publicly disclosed; no memory hardness against GPU/ASIC) | Argon2id m=64 MiB / t=3 / p=1 default, configurable up to m=256 MiB, t=16. Combined with a 128-bit Secret Key, enabled by default (opt-out supported at vault creation and any time in Settings). Memory-hard against GPU/ASIC; the Secret Key adds 128 bits of entropy that no master-password guess can recover. Matches 1Password Secret Key defence against offline backup brute force; Bitwarden has no equivalent extra-entropy mechanism. |
| AEAD construction | AES-256-GCM (AEAD) | AES-256-CBC + HMAC-SHA256 (Encrypt-then-MAC, also safe) | AES-256-GCM per item; OpenPGP (Curve25519) only for sharing and key wrapping | AES-256-GCM (AEAD). All four are safe; this is parity, not a moat. |
| Vault key at rest | Cloud-synced E2EE blob (server holds ciphertext) | Cloud-synced E2EE blob (server holds ciphertext) | Cloud-synced E2EE blob (server holds ciphertext) | Local-only, AES-GCM-wrapped by an Android Keystore key. Never leaves the device. |
| Offline brute-force surface | Cloud auth blob; Secret Key neutralizes brute force entirely | Cloud auth blob (KDF params known) | Cloud auth blob (bcrypt only) | No off-device auth blob. On Android, a leaked DB file alone is not brute-forceable - the verifier sits in Keystore-backed EncryptedSharedPreferences. 1Key backup files exported with Secret Key require BOTH the master password AND the Emergency Kit to decrypt, even if the file itself leaks. |
| Local DB column encryption | N/A - sync model relies on cloud ciphertext; on-device cache details vary | N/A - sync model relies on cloud ciphertext; on-device cache details vary | N/A - sync model relies on cloud ciphertext | Room columns (including title) stored as AES-GCM ciphertext with HKDF-derived subkeys + per-field AAD. Defends device forensic snapshots. |
Sources: 1Password Security Design white paper · Bitwarden KDF algorithms and kdf-config.ts · Proton Pass security model
1Key collects nothing. No analytics, no crash reporting, no telemetry, no usage data - not even anonymised. There is no backend, no account system, and no INTERNET permission in the manifest.
- All data is stored locally in an encrypted Room database
- The master password never leaves the device - not even a hash is transmitted
- Screenshots and Recent Apps previews are blocked by default via
FLAG_SECURE - The app requests the minimum possible permissions
The only things that leave your device are files you explicitly choose to export.
Full details: Privacy Policy →
1Key layers several independent protections so a failure in any one of them doesn't expose your data.
When you set a master password or PIN, 1Key derives a key from it using Argon2id (64 MiB memory, 3 passes). Argon2id is the OWASP-recommended password hash, and it's deliberately memory-expensive - not just CPU-expensive - so it can't be cheaply parallelised on GPUs or cloud farms. Even if someone got hold of your encrypted blobs, brute-forcing your password would mean allocating 64 MiB of RAM per guess, which is intractable for any decent password.
Every credential field - title, username, password, URL, notes, custom fields, TOTP secret - is encrypted separately with AES-256-GCM. Each field's encryption is bound to the specific row and column it belongs to via additional authenticated data (AAD), so an attacker with database write access can't swap one field's encrypted blob into a different column or a different row without the decrypt failing.
The vault key isn't used directly to encrypt fields. 1Key derives purpose-specific subkeys via HKDF-SHA256 - one for credential fields, another for titles. This means each subkey only sees the data it's meant to, and a future cipher rotation can target one subkey without affecting the others.
The vault key itself is wrapped (encrypted) by a key inside the Android Keystore, which lives in your device's secure hardware (TEE or StrongBox). That wrapping key never leaves the secure enclave. On Android 9+ it additionally requires the device to be unlocked at the time of use, so the vault is unreadable on a powered-on but locked phone.
The password verifier, PIN hash, and wrapped vault key all live in EncryptedSharedPreferences - a Keystore-bound encrypted file. So even if someone managed to extract the file from your device's storage, they couldn't read the verifier without live Keystore access - meaning offline brute-forcing of your password isn't possible.
.1key backups are encrypted with AES-256-GCM under an Argon2id-derived key. The backup header binds the export timestamp and the vault's version counter into the GCM authentication tag, so swapping a header field, a ciphertext body, or replaying an older backup against a newer vault all fail authentication.
Wrong-password and wrong-PIN attempts are tracked in DataStore (so killing and reopening the app can't reset the counter) and trigger escalating cooldowns:
| Failures | Cooldown |
|---|---|
| 3 | 30 seconds |
| 5 | 5 minutes |
| 10 | 1 hour |
After 3 wrong PINs, the user is forced to fall back to the master password - proving real identity before the easier path resumes. Biometric attempts have their own 3-strike counter that triggers the same fallback.
| Layer | Technology |
|---|---|
| Language | Kotlin |
| UI | Jetpack Compose + Material 3 |
| Architecture | MVVM + Clean Architecture |
| DI | Hilt / Dagger |
| Database | Room (SQLite) |
| Encryption | AES-256-GCM, Argon2id, HKDF-SHA256 |
| Auth metadata | EncryptedSharedPreferences (Keystore-bound) |
| Biometric | AndroidX Biometric + Android Keystore |
| OCR | ML Kit Text Recognition (on-device) |
| QR Scanning | ML Kit Barcode Scanning (on-device) |
| Async | Kotlin Coroutines + StateFlow |
| Navigation | Jetpack Navigation Compose |
git clone https://github.com/roufsyed/1key.git
cd 1key
./gradlew assembleDebugRequires Android Studio Hedgehog or later. No API keys, no .env files, no setup - clone and build.
| Permission | Reason |
|---|---|
CAMERA |
QR code scanning and OCR credential capture |
USE_BIOMETRIC |
Biometric unlock |
READ_EXTERNAL_STORAGE (Android ≤ 12) |
Reading backup files on older Android versions |
WRITE_EXTERNAL_STORAGE (Android ≤ 9) |
Writing backup files on older Android versions |
No INTERNET. No READ_CONTACTS. No ACCESS_FINE_LOCATION. Nothing else. On Android 13+ no storage permission is requested at all - backups go through the system file picker.
1Key is licensed under the GNU General Public License v3.0. You are free to use, study, modify, and redistribute it under the terms of that license.
The name "1Key", the wordmark, and the application icon are not licensed under the GPL and may not be used in derivative works - see TRADEMARKS.md.
1Key is licensed GPL-3.0 and you have every legal right to fork it. We ask that you don't, unless 1Key is unmaintained or is going somewhere you can't follow. Bug reports, security audits, and pull requests against this repository are far more useful to users than a parallel build.
If you do fork, you must rename the app, change the package ID, and remove the 1Key icon and wordmark per TRADEMARKS.md - users deserve to know whose binary they are trusting with their vault.
Footnotes
-
April 2026: Bitwarden's
@bitwarden/cli@2026.4.0npm package was briefly compromised (~334 installs over ~90 minutes) as part of the Checkmarx Shai-Hulud supply-chain attack. Bitwarden published an advisory the same day; no vault data was accessed and the malicious version was pulled. https://tech.yahoo.com/cybersecurity/articles/bitwarden-confirms-compromise-10-million-185341045.html ↩ -
Dashlane confirmed in June 2026 that attackers had stolen encrypted vaults for fewer than 20 personal-plan accounts. The attack (carried out in May 2026, disclosed in June 2026) used credentials reused from prior third-party breaches plus a brute-force on the 6-digit device-registration 2FA token to register rogue devices and download the encrypted vault payload. https://techcrunch.com/2026/06/02/password-manager-dashlane-says-hackers-stole-some-customers-password-vaults/ ↩
-
LastPass 2022 breach: backup database exfiltrated via a two-stage employee laptop compromise (corporate laptop, then a senior DevOps engineer's home machine with malware that captured the master password). Customer names, emails, phone numbers, and vault URLs were stored unencrypted in the leaked database. UK ICO fined LastPass £1.2M (~$1.5M) in December 2025 for inadequate security, citing 1.6 million UK users affected. https://www.forbes.com/sites/daveywinder/2025/12/14/lastpass-data-breach---insufficient-security-exposed-16-million-users/ ↩
-
1Password renders Markdown in secure notes after save - bold, italic, headings, lists, links. No live preview while typing. https://support.1password.com/markdown/ ↩
-
Bitwarden secure notes are plain text only; rich-text / markdown is a long-standing community feature request that is still open. https://community.bitwarden.com/t/add-additional-formatting-options-to-secure-notes-rich-markdown/14517 ↩
-
Dashlane secure notes have no markdown or rich-text formatting in their documented feature set. https://support.dashlane.com/hc/en-us/articles/202699381-Add-and-manage-Secure-Notes-in-Dashlane ↩
-
LastPass secure notes use structured field templates and have no markdown formatting documented. https://support.lastpass.com/help/manage-your-secure-notes-lp050001 ↩
-
Proton Pass secure notes are plain text only; markdown rendering is an open feature request on Proton's UserVoice as of 2026 and has not shipped. https://protonmail.uservoice.com/forums/953584-proton-pass-authenticator/suggestions/46872187-markdown-support-in-notes ↩
-
1Password 8 only offers unencrypted exports (1PUX / 1PIF / CSV / TXT) - per their own docs. The older encrypted "opvault" local-vault format was discontinued when 1P8 moved to cloud-only storage; the planned "1pex" encrypted export from 2021 has not shipped. https://support.1password.com/1pux-format/ ↩
-
1Password derives the encryption key with 650,000 iterations of PBKDF2-HMAC-SHA256 combined with a 128-bit Secret Key. https://support.1password.com/pbkdf2/ ↩
-
Bitwarden defaults to PBKDF2-SHA256 with 600,000 iterations. Argon2id is opt-in; default Argon2id parameters are m=64 MiB, t=3, p=4. https://bitwarden.com/help/kdf-algorithms/ ↩
-
Dashlane uses Argon2d with t=3 iterations, m=32 MiB ("32Mo" in their whitepaper), p=2. Legacy accounts may still be on PBKDF2-SHA2 200k; that path is being deprecated in 2026. https://www.dashlane.com/download/whitepaper-en.pdf ↩
-
LastPass currently mandates a 600,000-iteration PBKDF2-SHA256 minimum (raised after the 2022 breach). The pre-breach default was 100,100 iterations and many older accounts were configured as low as 5,000 - or even 1. https://blog.lastpass.com/posts/notice-of-recent-security-incident ↩
-
Proton Pass uses bcrypt for master-password derivation per their published security model. The specific cost factor is not disclosed. https://proton.me/blog/proton-pass-security-model ↩
-
1Key defaults to Argon2id with t=3, m=65,536 KiB (64 MiB), p=1, 256-bit output (the Standard preset); KDF parameters are configurable up to m=256 MiB, t=16 via custom presets. A 128-bit Secret Key is enabled by default, mixed into the Argon2id input via byte concatenation (Argon2id(MP || SK, salt, params)) and stored on-device under a StrongBox-preferred Keystore alias with TEE fallback. Opt-out is supported at vault creation, with enable/disable/rotate controls in Settings > Security > Secret Key. KDF presets and custom Argon2id parameters live in Settings > Security > Encryption strength. See
app/src/main/java/com/onekey/core/security/KdfPreset.kt,CryptoManager.kt, and the Secret Key implementation underfeature/secretkey/. ↩





