Split a secret into printable cards. Any K of N recover it. Fully offline.
This is the Android port of QuorumPony (iOS). It splits a secret — an age or GPG key, a seed phrase, a password — into N shares using Shamir's Secret Sharing over GF(2⁸), prints them as cards (QR + hand-typeable Crockford base32), and recovers them by camera or keyboard.
| Module | What it is |
|---|---|
:core |
QuorumPonyCore, Kotlin port. Pure JVM — no Android dependencies. GF(2⁸), Shamir split/combine, the QPW1 envelope, QPS1 share framing, Crockford base32. |
:app |
Jetpack Compose app: split, recover (CameraX + ZXing scanning), check-a-card, printable PDF export, biometric lock, six languages. |
The Swift core, the Python reference (qpref.py), and this Kotlin port all
verify against the same committed vector file,
core/src/test/resources/test_vectors.json — byte-for-byte share equality,
not just round-trips. Two independent implementations agreeing is stronger
evidence than one implementation compiled twice; that is the property that
matters for a format where a bug means a permanently unrecoverable backup.
./gradlew :core:test # runs the ported unit tests + vector pins
The deterministic RNG used by the vectors is defined as the continuous
keystream SHA-256(seed ‖ counter_be64), consumed in a fixed order
(setID → envelope pad → per-byte coefficients). Production splits use
SecureRandom.
Requires JDK 17+ and the Android SDK (compileSdk 35). Then:
./gradlew :app:assembleDebug
Release builds are unsigned by design — F-Droid signs its own builds, and local releases should be signed with your own keystore.
- QR generation: Nayuki's QR-Code-generator (MIT) — explicit error correction control, no dependencies; the same generator family the iOS 2.0 plan pins for byte-identical output across platforms.
- QR scanning: CameraX + ZXing core (Apache-2.0, pure Java). No native
.solibraries, which keeps F-Droid reproducibility simple. QPS1 share QRs are far below version-40 density, where ZXing is weakest; if the v2 Paper Archive lands on Android, revisit zxing-cpp vs BoofCV per the plan. - PDF:
android.graphics.pdf.PdfDocument— platform API, real embedded fonts, zero APK cost. US Letter geometry mirrors the iOSCardPDF. - Biometric:
androidx.biometric1.1.0 with device-credential fallback, and the same fail-open rule as iOS: a device with no lock configured never locks the user out of their own backups. - No network permission. Nothing to toggle, nothing to audit.
- Localization uses standard Android resources generated from the iOS string table (en, es, de, fr, ja, pt-BR) with in-app switching via per-app locales.
- Licence: Apache-2.0 (SPDX in every file).
- No Play Services, Firebase, analytics, or proprietary blobs; all dependencies are FLOSS from Maven Central / Google's repo.
- Reproducibility:
dependenciesInfodisabled, resource optimizations off, unsigned release artifacts. - Store listing metadata lives in
fastlane/metadata/android/(six locales). - A starting
fdroiddatarecipe is inmetadata/app.quorumpony.yml.example.
./gradlew :app:bundleRelease produces the AAB. Data-safety form: no data
collected, no data shared; the camera is used only for on-device QR scanning.
Apache-2.0. See LICENSE.