peach-android
A free, open source, local-first password manager for Android.
timeline
atlas348 files
app/
drafts/
MF1MF2/
peach-browser source (read-only; never modified).ExportRoundTripTest.ktgen_peach_fixture.mjsImportParsersTest.ktImportScreen.kt───────────────────────────────────────────────────────────────────────────── ViewModel ─────────────────────────────────────────────────────────────────────────────mf1_kat_gen.mjsGenerates an MF-1 known-answer vector using the BROWSER's exact recovery algorithm (recovery-words.ts) against the REAL browser word list.parse_android_export.mjsPeachPayloadCodec.ktPeachScript binary payload (PCHS) — a byte-for-byte port of the browser's peachPayload.ts (MF-2).PeachScript.ktPeachScript outer codec — maps each payload byte to one Private-Use-Area code point in U+E000..U+E0FF, and back.PeachScriptExport.ktPeachScript export (MF-2) — writes the browser's PCHS binary payload (Argon2id + AES-256-GCM, zstd sections, BLAKE3 checksum, size-bucket padding, string-table entry packing) re-encoded into Private-Use-Area text.PeachScriptImport.ktPeachScript import (MF-2) — parses the browser's PCHS binary payload back into full vault entries.PeachScriptTest.ktRecoveryEscrowTest.ktRecoveryWords.ktVaultCrypto.ktVaultRepository.ktVaultStore.ktOne encrypted slot at rest.src/
androidTest/
java/
debug/
res/
values/
main/
java/
com/
peachpasswords/
autofill/
hiltViewModel() without reaching for an EntryPoint accessor.AutofillResponseBuilder.ktTurns parsed form fields + vault entries into autofill [Dataset]s — the menu RemoteViews row, the inline keyboard chip, and the actual field values.AutofillSave.ktPeachAutofillService.ktSystem autofill provider.TrustedBrowsers.ktConservative allowlist of apps permitted to request autofill for a web origin (MF-7).codex/
popup/codex/pdf-layout.ts, which is the canonical Codex page format.CodexPdf.ktRenders the Aztec codes onto an A4 PDF in a 6×6 grid — the printed Codex.CodexRestore.ktRestore side: render a Codex PDF back to bitmaps, crop the 6×6 grid using the same geometry [CodexPdf] laid down, decode each Aztec, then Reed-Solomon reconstruct the payload — surviving missing or unreadable codes up to the parity budget.CodexTypes.ktCodex on-paper format constants and shapes — port of the browser shared/codex-types.ts.ReedSolomon.ktSystematic Reed-Solomon erasure codec over GF(2⁸), Backblaze/JavaReedSolomon construction (Vandermonde matrix made systematic).di/
feedback/
haptics/
passkeys/
shared/
sync/
revoked array to the signed body.DeviceType.ktWhat kind of device a peer is, on the wire and in the paired-device store.ForegroundSyncCoordinator.ktNoiseKK.ktNoiseNK.ktPairedDevice.ktPairedDeviceStore.ktPersistent registry of paired devices, encrypted at rest with EncryptedSharedPreferences (same construction as DuressConfigStore / LicenseRepository, v2.1.36).PairIdentityFrames.ktThe PAIR_IDENTITY frame: who a peer claims to be, exchanged inside the encrypted session once and pinned thereafter.PairingAuth.ktPairingFrames.ktLength-delimited frame IO for a pairing/sync connection.PairingInvitation.ktPairingSession.ktThe user's SAS decision, handed to the UI and awaited by the live pairing session.PeachSyncService.ktKeeps this device reachable on the relay so an already-paired peer can reconnect.PeachWebSocket.ktA minimal RFC 6455 server endpoint — just enough of the protocol to talk to a browser extension's new WebSocket(...).PendingVouchedDeviceStore.ktRelayAdoptionHost.ktRelayAdoptionReceiver.ktReceiver half of relay-first vault adoption.RelaySettingsStore.ktSync is exactly three named choices (docs/sync-lan-retirement.md, mirroring the browser's sync-settings.ts):Rendezvous.ktRustNoiseNative.ktThin JNI boundary over the canonical Rust snow state machine.SASDerivation.ktSyncAlert.ktSyncAlertStore.ktSyncCoordinator.ktSync — Phase 2 manifest-diff coordinator.SyncIdentity.ktSyncLimits.ktCloudflare Workers caps one WebSocket message at 32 MiB.SyncMessage.ktSync wire protocol — exact port of the browser SyncMessage union (shared/sync-types.ts).SyncOutcomeReason.ktWhy a sync attempt ended, in the same vocabulary the browser uses (src/shared/sync-outcome.ts).SyncOutcomeStore.ktThe single place a sync attempt is allowed to end.SyncPadding.ktE7: frame padding at the relay boundary.SyncPeerRole.ktWho speaks first in a relay room.SyncSession.ktTransport-neutral session consumed by the sync coordinator.VaultAdopt.ktVault adoption frame protocol — exact port of the browser shared/vault-adopt.ts.VaultSyncAdapter.ktProduction [SyncVaultAdapter] backing the coordinator with the live [VaultRepository].ui/
codex/
components/
PairDeviceFlow.tsx (a finch and a swallow) rather than redrawn by eye.PeachEmptyOrEndState.ktPeachExpandableCard.ktPeachField.ktPeachMark.ktThe Peach brand mark — a peach fruit with a single leaf.PeachSegmentedControl.ktPeachTopBar.ktQaFlags.ktDebug-only, opt-in escape hatch so automated visual QA (screenshot-based Gate 2 comparisons) can capture screens that are normally FLAG_SECURE-protected.RuneGridBackground.ktSecureFlagEffect.ktSets WindowManager.FLAG_SECURE while this composable is in the composition and clears it on dispose — blocking screenshots, screen recording, and the recents thumbnail of screens that display secrets (MN-3: recovery words, export blob, codex generation).SyncIndicatorDot.ktThe sync indicator light, shared by the vault list and the Sync settings card so the two can never disagree.TOTPRing.ktA small ring that sweeps once per TOTP period and turns breach-red in the final 5 seconds.lock/
onboarding/
pairing/
recovery/
security/
settings/
theme/
vault/
animating).TagChipEditor.ktMax tags per entry.TagListWidgets.ktHorizontally scrollable tag filter strip for VaultListScreen, placed between the search bar and the sort bar.TotpInlineEdit.ktE6 — TOTP double-tap to edit the 2FA secret, inline in EntryDetailScreen.TrashScreen.ktVaultHealthScreen.ktWarm amber used for the "reused" and "weak" advisory buckets.VaultListScreen.ktVaultListViewModel.ktupdates/
GET https://kepr.uk/api/<repo>/releases/latest, flattened to the single platform this app can install.UpdateRepository.ktThe Kepr side of in-app updates: what the newest release is, fetching its APK, and proving that APK is the one Kepr published before it is ever handed to the package installer.vault/
privateKeyJwk whether it arrives as a JSON object or a string, and writes it back as an object.LastViewedEntryStore.ktRemembers the id of the entry the user last opened so a fresh unlock can land straight back on it (matching the extension, which opens the last entry rather than the list).PasskeyData.ktPasswordGenerator.ktCryptographically random password generator.PasswordHistoryItem.ktOne past password kept in [VaultEntry.passwordHistory].PeachPayloadCodec.ktPeachScript binary payload (PCHS) — a byte-for-byte port of the browser's peachPayload.ts (MF-2).PeachScript.ktPeachScript outer codec — maps each payload byte to one Private-Use-Area code point in U+E000..U+E0FF, and back.RecoveryWordList.ktRecovery word list — byte-identical to the browser's src/shared/recovery-word-list.ts: the canonical 2048-word BIP39 English list, 0-indexed, no duplicates.RecoveryWords.ktSavedIdentity.ktTOTPGenerator.ktRFC 6238 TOTP / RFC 4226 HOTP.VaultCrypto.ktVaultEntry.ktVaultHealth.ktVaultLockTimer.ktIdle auto-lock timer.VaultRepository.ktLenient parser for the Codex vault-blob wrapper only.VaultSettings.ktVaultSnapshot.ktVaultStore.ktOne encrypted slot at rest.jniLibs/
arm64-v8a/
armeabi-v7a/
x86_64/
res/
drawable/
font/
layout/
mipmap-anydpi-v26/
values/
test/
java/
com/
peachpasswords/
codex/
feedback/
license/
security/
shared/
sync/
sync-settings.test.ts.RelaySettingsPropagationTest.ktWhat a relay change does to the existing mesh, mirroring the browser's setSyncMode / setRelayUrl.RendezvousTest.ktSyncAlertTest.ktSyncCoordinatorTest.ktTwo in-memory [SyncSession]s wired back to back.SyncOutcomeTest.ktThe indicator light is the whole point of this vocabulary, so the mapping is swept exhaustively rather than sampled: a reason added later has to be given a place here or the sweep fails.SyncPaddingTest.ktSyncServiceStartTest.ktThe service start is the first step of every sync path, and it was the one step that could throw straight out of a button press: Android 12+ refuses a foreground service started from the background, and startForegroundService was called bare.SyncSuiteTest.ktSync suite (brief Suite 13): length-prefixed pairing frames, SAS derivation KAT, and cross-device entry sync through the [VaultSyncAdapter] (two repositories made to share a sync root key via the Codex blob).VaultAdoptTest.ktAdoption frame protocol parity with the browser vault-adopt.test.ts.VaultSyncAdapterTest.ktui/
lock/
onboarding/
vault/
updates/
vault/
privateKeyJwk is a JSON OBJECT in the browser (JsonWebKey in shared/types.ts); Android holds it as a compact string.BrowserSlotTest.ktPins the browser→Android slot-A translation that Codex restore depends on.CardSerializationTest.ktIn-memory [VaultStorage] for exercising last4 derivation on save (MF-3).CrossPlatformRecoveryWordsTest.ktRecovery words are only a human-readable encoding of the root key's first 16 bytes, so the two platforms MUST agree on the word list byte for byte.DuressSlotBTest.ktIn-memory [VaultStorage] including a decoy (slot B) slot, for the MF-6 duress model.OfficialCryptoVectorsTest.ktPasskeyEntryTest.ktPasswordGeneratorTest.ktPeachScriptRoundTripTest.ktPeachScript + CSV round-trip suite (brief Suite 7): large-vault fidelity, ciphertext tamper detection, size-bucket padding, and CSV column/injection behavior.PeachScriptTest.ktRecoveryEscrowIntegrationTest.ktIntegration coverage for the full create → confirm → seal → unlock recovery chain (brief Fix 1).RecoveryEscrowSuiteTest.ktRecoveryEscrow suite (brief Suite 3): word validation/autocomplete, partial and wrong-word failures, missing-escrow handling, recovery-driven password reset, and the duress-mode guard that recovery escrows are never sealed for the decoy.RecoveryEscrowTest.ktSlotAUnlockTest.ktIn-memory [VaultStorage] for the non-committing dual-derivation path (MF-5).SlotPaddingTest.ktExposes the raw stored slots so the padding lengths (MN-1) can be inspected.TOTPGeneratorTest.ktVaultCryptoKdfTest.ktMF-4: the Argon2id KDF must hash the password's explicit UTF-8 bytes (matching the browser's TextEncoder().encode), not its UTF-16 code units.VaultCryptoTest.ktVaultCrypto suite (brief Suite 2): Argon2id key derivation, AES-256-GCM round-trips, AAD enforcement, and KDF parameters.VaultHealthTest.ktVaultHealth suite (brief Suite 8): the pure [VaultHealth.buildReport] scoring — breach / reused / weak / aged / sensitivity detection, section counts, and the sensitivity-weighted vault score.VaultLockTimerTest.ktIn-memory [VaultStorage] so the timer can drive a real repository off-device.VaultRepositoryExtraTest.ktSecond VaultRepository suite (brief Suite 1 expansion).VaultRepositoryTest.ktIn-memory [VaultStorage] so the repository can be exercised without Android.widget/
gradle/
app/build.gradle actually declares versionName "2.2.0" / versionCode 202000.settings.gradleVERSIONhistory
details
Peach for Android
A free, open source, local-first password manager for Android.
No accounts. No subscription. Your passwords stay on the device, encrypted with AES-256-GCM and protected by Argon2id key derivation. Sync, backup, and autofill happen without trusting any cloud in the middle.
Features
- Zero-knowledge vault — AES-256-GCM encryption, Argon2id KDF, keys never leave your device
- End-to-end encrypted sync — pairs with your other Peach devices over a Noise channel; the relay only forwards ciphertext it cannot read
- Inline autofill — fills directly in apps, no copy-paste detour
- Passkeys — WebAuthn credentials alongside your passwords
- Quick Settings tile — copy a credential from anywhere with a single tap
- Biometric unlock — hardware-backed AndroidKeyStore escrow, invalidated on enrollment change
- Codex — prints your encrypted vault as Aztec codes on paper. Physical offline backup
Open Source
Peach is free and open source under the GPL v3 license. Both the browser extension and the Android app.
The source is hosted on Kepr — Asha Software's own version control platform.
Security
Peach has undergone two adversarial analysis sessions against this codebase. The most recent findings have been resolved.
Cryptographic primitives:
- Key derivation: Argon2id (m=64MiB, t=3, p=4)
- Encryption: AES-256-GCM with fresh random nonces
- Sync handshake: Noise NK / Noise KK (25519, ChaChaPoly, BLAKE2s)
- Backup codec: GF(2⁸) Reed-Solomon with zstd compression
- BLAKE3 checksums throughout
The canonical Noise core lives in a shared Rust crate with the browser extension — Android drives it via JNI. See docs/CRYPTOGRAPHIC-TEST-VECTORS.md for the byte-level vectors that pin each primitive.
Building
./gradlew assembleRelease
Outputs to app/build/outputs/apk/release/. The shared Noise core is built from ../peach-browser/crypto-core.
License
GPL v3 — see LICENSE.
Peach Pro
Pro features (end-to-end encrypted sync, Codex, Canary) are available for $39 one-time at peachpasswords.com. Purchasing Pro supports continued development.
Built by Asha Software · [email protected]