peach-android
A free, open source, local-first password manager for Android.
timeline
atlas351 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/
shared/chirp-adopt.ts.ChirpIdentity.ktChirpSyncCoordinator.ktChirp Sync — Phase 2 manifest-diff coordinator.ChirpSyncSession.ktTransport-neutral session consumed by the sync coordinator.ChirpTypes.ktCloudRelayReconnectListener.ktCodePairingServer.ktCode-based pairing, phone side.CryptoCompare.ktFixed-format protocol comparisons.DeviceManifestSupport.kt0x02 added the revoked array to the signed body.ForegroundSyncCoordinator.ktMdnsPairingServer.ktC7 TCP + mDNS reconnect SERVER (responder side).NoiseKK.ktNoiseNK.ktPairedDevice.ktPairedDeviceStore.ktPersistent registry of paired devices, encrypted at rest with EncryptedSharedPreferences (same construction as DuressConfigStore / LicenseRepository, v2.1.36).PairingAuth.ktPairingCode.ktThe compact join code this phone displays and the user types into the browser.PairingDiscoveryClient.ktC7 TCP + mDNS reconnect CLIENT (initiator side).PairingFrames.ktLength-delimited frame IO for a pairing/sync connection.PairingInvitation.ktPairingProgress.ktPeachSyncService.ktKeeps the pairing/sync listener reachable.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.RelayFrames.ktBrowser-to-browser relay frames — the wire addition from PEACH_SYNC_RELAY_DESIGN.md §3, made concrete.RelayHub.ktWhether this device will relay for others.RelaySettingsStore.ktWhether this device relays sync traffic for other paired devices.Rendezvous.ktRustNoiseNative.ktThin JNI boundary over the canonical Rust snow state machine.SASDerivation.ktSyncAlert.ktSyncAlertStore.ktSyncIdentity.ktSyncLimits.ktCloudflare Workers caps one WebSocket message at 32 MiB.SyncMessage.ktChirp Sync wire protocol — exact port of the browser ChirpSyncMessage union (shared/sync-types.ts).SyncPadding.ktE7: frame padding at the relay boundary.SyncReconnectListener.ktThe everyday sync path: already-paired devices reconnecting without a code.SyncStatus.ktVaultSyncAdapter.ktProduction [ChirpSyncVaultAdapter] backing the coordinator with the live [VaultRepository].ui/
codex/
components/
ChirpPairingFlow.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).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/
values-night/
test/
java/
com/
peachpasswords/
codex/
license/
security/
shared/
sync/
chirp-adopt.test.ts.ChirpSyncCoordinatorTest.ktTwo in-memory [ChirpSyncSession]s wired back to back.ChirpSyncSuiteTest.ktChirpSync 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).CloudRelayReconnectListenerTest.ktCodePairingServerTest.ktCovers the two behaviours that are easy to get quietly wrong: a bad token must be refused with no reply at all, and an abandoned code must stop working.ForegroundSyncCoordinatorTest.ktNoiseKKTest.ktPairingAuthTest.ktPairingCodeTest.ktThe phone is the only side that generates pairing codes and the browser is the only side that reads them, so a drift here is invisible until a real pairing fails with nothing to look at.PairingInvitationTest.ktPeachWebSocketTest.ktExercises the server against OkHttp's RFC 6455 client rather than a hand-rolled one.RelayAdoptionHostTest.ktRelayFramesTest.ktThe relay frames share a channel with ordinary sync frames, so the one thing that must never break is telling them apart: a sync frame misread as a relay frame would be forwarded to another device, and a relay frame misread as sync would be handed to the vault.RelayHubTest.ktThe relay's whole job is to move bytes it must not understand between two peers that cannot reach each other.RelaySettingsPropagationTest.ktRendezvousTest.ktSyncAlertTest.ktSyncPaddingTest.ktSyncReconnectListenerRelayTest.ktThe dispatch itself, over a real socket and a real Noise session: two paired "laptops" connect, one asks to be relayed to the other, and a frame crosses.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]