74012541d205
docs: trim README to description + security only
- time
- 2026-08-01 14:08 UTC · 2 months ago
- machine
- koh2
- parent
- 33507f973788
↓ peach-android-74012541.tar.gzatlas at this save
files changed1 file
README.md+26 −80README.md+26 −80
@@ -1,95 +1,41 @@1-# peach-android1+# Peach for Android22 3-The Android companion app for [Peach Password Manager](https://peachpasswords.com). Free, open source, local-first. Vault stays on the device, encrypted with AES-256-GCM, protected by Argon2id.3+A free, open source, local-first password manager. Your vault stays on the device, encrypted with AES-256-GCM and protected by Argon2id. Sync between your devices happens over an end-to-end authenticated Noise channel; the cloud relay only forwards ciphertext it cannot read. There are no accounts, no servers holding your data, and no subscription required.44 5+Peach pairs with the Peach browser extension, prints encrypted backups as Aztec codes on paper, autofills inline in apps and browsers, and stores passkeys alongside passwords.6+57 **Current version:** v2.9.206-**Source:** [kepr.uk/peach-android](https://kepr.uk/peach-android)78 **License:** GPL v39+**Source:** [kepr.uk/peach-android](https://kepr.uk/peach-android)810 911 ---1012 11-## What this repo is13+## Security1214 13-Production Android app for Peach. Kotlin + Jetpack Compose + Hilt, single `:app` module. Holds the vault on-device, syncs to other paired devices over a Noise NK/KK channel through a cloud relay, and provides inline autofill, Quick Settings tile, passkey support, Codex paper backup, and updates-from-Kepr.15+### Cryptographic primitives1416 15-Not a fork and not a port — every byte-level decision (Argon2id parameters, per-entry sync envelope, Codex RS/Deflate/Aztec envelope, Noise NK/KK wire format, vault slots, recovery escrow) is verified against the browser implementation in `peach-browser`. See [`docs/browser-parity-map.md`](./docs/browser-parity-map.md) for the per-primitive parity contract.17+- **Key derivation** — Argon2id (`m=64 MiB`, `t=3`, `p=4`, 32-byte output, 16-byte CSPRNG salt)18+- **Vault encryption** — AES-256-GCM with a fresh 96-bit random nonce per encrypt and 128-bit authentication tag19+- **Sync handshake** — Noise NK (pairing) and Noise KK (adoption), `25519_ChaChaPoly_BLAKE2s` cipher suite20+- **Per-entry sync envelope** — distinct HKDF-derived AES-256-GCM key per entry, AAD bound to the entry id so a ciphertext cannot be replayed between slots21+- **Keyed storage** — paired-device and license stores use `EncryptedSharedPreferences`; vault slots are AES-GCM-sealed blobs in plain prefs (only the salt is cleartext, matching the browser model)22+- **Biometric escrow** — hardware-backed AndroidKeyStore AES-256-GCM key with `setUserAuthenticationRequired(true)` and `setInvalidatedByBiometricEnrollment(true)`23+- **Codex (paper backup)** — GF(2⁸) Reed-Solomon with zstd compression and Aztec codes at 25% ECC24+- **Checksums** — BLAKE3 throughout1625 17----26+### Key handling1827 19-## Repository layout28+- Master key and derived key are zeroed on lock and in `finally` blocks along all transient paths29+- No secret material is ever logged. There is no online breach check — no password hash or plaintext is ever transmitted anywhere30+- `allowBackup="false"` + `fullBackupContent="false"` — vault does not participate in Android Auto Backup2031 21-```22-app/src/main/java/com/peachpasswords/23- sync/ Pairing, Noise handshakes, relay dialer, mesh manifest24- autofill/ Inline + Accessibility autofill providers25- codex/ Aztec encoder, RS erasure, deflate codec26- passkeys/ WebAuthn / passkey storage and assertion27- ui/ Compose screens (Lock, Vault, Settings, Trash, etc.)28- qs/ Quick Settings tile29- di/ Hilt modules30- shared/ Cross-screen utilities32+### Tested against published vectors3133 32-docs/ Cryptographic vector provenance, browser parity map, audit33-app/drafts/ One-off integration drafts (often retired)34-```34+All primitive implementations are pinned to published test vectors in `docs/CRYPTOGRAPHIC-TEST-VECTORS.md`:3535 36-The canonical Noise core (`NK` and `KK` patterns, X25519, ChaCha20-Poly1305, BLAKE2s, nonce state) lives in **`../peach-browser/crypto-core`** as a Rust crate. Android drives it via JNI; see [`docs/NOISE-CORE-PROVENANCE.md`](./docs/NOISE-CORE-PROVENANCE.md).36+- RFC 9106 §5.3 Argon2id37+- NIST CAVP `gcmDecrypt256.rsp` (group `PTlen=128`, `AADlen=0`, `Taglen=128`)38+- BLAKE3 official `input_len=1024` reference input39+- Cacophony Noise NK / KK transcript catalog (shared with `peach-browser/crypto-core`)3740 38----39-40-## Building41-42-Requires JDK 17, Android SDK 34, NDK r26+, Rust toolchain.43-44-```bash45-# 1. Build the shared Noise core (one time, or whenever the crate changes)46-(cd ../peach-browser/crypto-core && cargo build --locked --release)47-48-# 2. Build the app49-./gradlew assembleRelease # signed release APK50-./gradlew assembleDebug # debug APK with com.peachpasswords.debug id51-./gradlew testDebugUnitTest # sync + vault + crypto unit tests52-```53-54-Outputs land in `app/build/outputs/apk/{release,debug}/`. CI uses [`scripts/kepr-build-apk.sh`](./scripts/kepr-build-apk.sh) which signs and uploads to Kepr under a platform allowlist (currently `android-arm64`).55-56-The single source of truth for the version is the repository-root [`VERSION`](./VERSION) file. `versionName` in `app/build.gradle` reads it directly; `versionCode` is derived deterministically from the version string.57-58----59-60-## Sync model61-62-- **Pairing** — invitation over the cloud relay; Noise NK handshake establishes the rendezvous secret.63-- **Adoption** — one device (source) commits its encrypted vault to another (receiver) via an authenticated Noise KK channel. The source ships a snapshot; the receiver reconstructs entries + tombstone state + duress slot, then exchanges a signed device-manifest for the mesh.64-- **Mesh propagation** — every device advertises a `deviceManifestVersion` in `SYNC_HELLO`. When both peers advertise the same version, signed device graphs are exchanged even on equal entry versions so introductions and revocations converge across multi-hop edges.65-- **Revocations are terminal** — once a device's id or long-term key lands in the revocation list, no manifest re-admits it. `isDeviceRevoked(deviceId, longTermPublicKeyHex)` checks both, keyed on the key as well as the id so a revoked key can't walk back in under a fresh id.66-67-See [`docs/CRYPTOGRAPHIC-TEST-VECTORS.md`](./docs/CRYPTOGRAPHIC-TEST-VECTORS.md) for the byte-level vectors that pin this implementation to RFC 9106 Argon2id, NIST CAVP AES-GCM, BLAKE3 reference input, and the Cacophony Noise NK/KK test catalog.68-69----70-71-## Audits72-73-[`peach-android-audit-report.md`](./peach-android-audit-report.md) records the most recent read-only adversarial review against `peach-browser`. Cryptographic primitives are clean and byte-equivalent; lifecycle and parity findings are tracked against the version that received them and resolved in subsequent saves.74-75----76-77-## Version control78-79-This repo uses Koh, not git. Snapshots live locally and are offered to [kepr.uk](https://kepr.uk) for review and distribution.80-81-```bash82-koh status # current working tree83-koh save "feat: ..." # atomic save84-koh checkpoint # pre-anything-risky restore point85-koh offer peach-android # push to kepr.uk86-koh offer peach-android --builds # build + publish APKs87-```88-89-`.agent/CONTINUITY.md` is the live handoff file for any session that has to stop mid-campaign.90-91----92-93-## License94-95-GPL v3 — see [`LICENSE`](./LICENSE).41+The canonical Noise core (X25519, ChaCha20-Poly1305, BLAKE2s, nonce state, rekey) lives in the Rust crate at `../peach-browser/crypto-core` and is driven from this app via JNI — see `docs/NOISE-CORE-PROVENANCE.md`. Every cryptographic decision in this codebase is byte-equivalent to the browser implementation; the parity contract is documented in `docs/browser-parity-map.md`.