Skip to content

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 15:57
· 33 commits to main since this release
v1.3.0
615db7c

Everything in v1.2.0, plus on-device signing-group creation and the hardware-backed storage work around it.

A signing group can be created on the device

Creating a signing group previously meant running the ceremony elsewhere. The app now runs distributed key generation itself, with the roster built from codes the members scan off each other, and the fingerprint, validation and assembly done in Rust rather than Kotlin (#502), so the roster the ceremony commits to is the one the core checked. It is offered from the account switcher (#485), and a cancel targets the ceremony by run id, so a late progress update cannot cancel a different run or clobber one that already finished (#515).

An interrupted ceremony no longer strands a key share

A ceremony that stops partway leaves a share on the device. That share now lives under its own auth-gated Keystore alias (#488), is detected at launch, and can be recovered or discarded only after device authentication (#492). Group creation is gated until that check has completed, and fails closed while the marker is unreadable (#494). An alias that is not auth-gated is refused outright for a new ceremony rather than reused (#505).

The DKG secret survives a StrongBox that cannot use its own key

Some devices generate a StrongBox key successfully and then fail when it is actually used. The DKG keypair falls back when StrongBox is unavailable (#495), and an AES key that passes generation but fails a use-time encrypt probe, or throws on cipher init, now falls back to the TEE instead of leaving storage holding a key that cannot encrypt (#503). The probe covers auth-gated keys as well, which it previously skipped (#506).

Refusing a request remembers that decision for as long as you chose

The remember-decision duration was applied when a request was approved but dropped when one was refused, so a refusal made with a duration set still asked again on the next request (#476).

A decrypt fault at launch cannot crash the app or open the gate

A storage decrypt fault while loading accounts took the launch down with it. That load is now guarded, and on failure the pending-DKG slot is marked unreadable so the group-creation gate fails closed rather than open, with the check completing either way so the gate cannot latch on waiting (#499).

The RNG hygiene gate cannot be walked past

The CI guard introduced in v1.2.0 scanned for tokens, so a member access split after a trailing dot, and a class name assembled by concatenation, both walked past it with nothing to notice. Both bypasses are closed, and the guard now self-tests and fails loudly when a probe is not staged, so a regression in the guard itself is caught instead of quietly weakening the check (#473).

keep moves to v0.10.0

keep.version moves to keep v0.10.0. That is load-bearing for this release rather than routine: the previous pin sat short of it by exactly the commits this release's DKG path depends on, which are transport keys derived from each member's share, the coordinator's group id pinned for the ceremony, a fix for group-key verification rejecting every key, multi-cosigner round fixes with every peer bound from any share, cleanup of abandoned DKG subkey entries, and a rustls bump for RUSTSEC-2026-0285.

Install

Download the APK for your device's architecture from the Assets below. Min SDK 33 (Android 13+).

  • keep-android-v1.3.0-arm64-v8a.apk for physical devices
  • keep-android-v1.3.0-x86_64.apk for emulators and x86_64 hardware

Both per-ABI APKs reproduce bit-for-bit from source: the Reproducibility workflow rebuilds each one in a pinned container and compares it against the published artifact with apksigcopier compare, so a mismatch fails rather than passing quietly.

Verifying this release

Download SHA256SUMS, SHA256SUMS.asc, privkeyio-signing-key.asc and your APK into one folder:

gpg --import privkeyio-signing-key.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS

Look for Good signature from "Kyle Santiago <kyle@privkey.io>" on key A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38, and OK for your file. The warning that the key is not certified is expected, and means only that you have not marked it trusted yourself.

The APK carries its own signature, which is what Android checks on install and what F-Droid pins as AllowedAPKSigningKeys:

apksigner verify --print-certs keep-android-v1.3.0-arm64-v8a.apk

That must report certificate SHA-256 digest 3eb0e6f6f4e0962ebd717f84eea47428b73087b686c956633d6a9fcc4c854f50.

The git tag is signed with the same GPG key, so git verify-tag v1.3.0 checks the source this release was built from.

Full changelog

v1.2.0...v1.3.0