Skip to content

Sync upstream (pubky 0.10) + fix Android TLS "Revoked" on pkarr's relay client - #2

Merged
jvsena42 merged 3 commits into
mainfrom
chore/sync-upstream-0.10
Aug 24, 2026
Merged

Sync upstream (pubky 0.10) + fix Android TLS "Revoked" on pkarr's relay client#2
jvsena42 merged 3 commits into
mainfrom
chore/sync-upstream-0.10

Conversation

@jvsena42

Copy link
Copy Markdown
Owner

Two commits: the upstream sync, then the fix it does not cover. Both are needed — measured on-device, neither alone stopped the errors.

The bug

Loopky was reporting "You're offline" on every Pubky-reading screen, on devices with a working connection. Under it:

certificate was revoked: java.security.cert.CertPathValidatorException:
    Certificate does not specify OCSP responder
→ invalid peer certificate: Revoked
→ HTTP transport error: error sending request for url (https://_pubky.…)

rustls-platform-verifier hard-fails revocation checking on Android: Let's Encrypt no longer publishes an OCSP responder, Android's PKIXRevocationChecker only tries OCSP, and the crate's Kotlin half turns the resulting CertPathValidatorException into StatusCode.Revoked. The crate's own escape hatch for this is gated on BuildConfig.TEST, so it never applies to a shipped app, and 0.7.0 is the latest release and still carries the bug (their PR #179 is the pending real fix). There is no version to upgrade to.

Upstream pubky/pubky-core-ffi has this too — same rustls-platform-verifier = "0.7.0", same src/rustls_init.rs. Anyone shipping it on Android is exposed.

Commit 1 — sync to upstream@74fea50 (pubky 0.10)

pubky 0.10 builds its ICANN client with webpki roots and revocation off (icann_tls_config_without_revocation_check). That is half the fix.

  • Source merged clean. One fork-only call site needed the 0.10 signature: put_bytes threads a client_id through signin, matching what upstream did to put/delete_file/sign_in/sign_up/start_auth_flow.
  • Every conflict was a generated artifact, resolved by regenerating, not by picking a side — upstream's binaries are built from upstream's source and carry none of this fork's added functions. Android (4 ABIs, llvm-stripped to match upstream), iOS xcframework + Swift, and Python are all rebuilt from this tree.

Commit 2 — the half 0.10 does not reach

pkarr builds its relay HTTP client from reqwest's defaults, which on Android is still the platform verifier. After the bump alone the device logged 8 more Revoked failures, every one immediately after:

pubky::actors::pkdns: Resolving homeserver for public key … via PKARR

So _pubky.<key> resolutions that fell back to the relay kept dying. Resolutions the DHT answered succeeded — which is exactly why this presented as intermittent rather than total.

pkarr 7 exposes ClientBuilder::reqwest_client and pubky 0.10 exposes .pkarr(..), so the relay client gets the same treatment upstream gave the ICANN one. Reaching it means constructing through PubkyHttpClient::builder() + Pubky::with_client.

Dropping revocation checking is upstream's own choice for this problem, and the trade is narrow here: these are relay lookups of public, signed pkarr records, and the record's signature — not the transport — is what makes the answer trustworthy.

reqwest goes 0.12 → 0.13 to match: the client handed to pkarr is only type-compatible at the same crate version, and the fork used reqwest directly in exactly one place, so this removes a duplicate reqwest from the tree rather than adding one.

Verified on-device

Redmi Note 11, Android 13, release build, same account and navigation each time:

ClassNotFound "Revoked" transport errors result
before the AAR fix 42 many every handshake failed
AAR fix only 0 8 3 Home failed to load
+ pubky 0.10 only 0 8 3 still failing (relay)
+ this PR 0 0 0 session resolves in 1.8 s, not 12

Not addressed

libpubkycore.so still has a GNU_RELRO segment aligned to 0x1, so it is not 16 KB page-size compatible. Pre-existing, and a Play blocker in its own right.

pwltr and others added 3 commits August 21, 2026 14:19
Syncs the fork with pubky/pubky-core-ffi@74fea50, which bumps the pubky SDK
0.9.3 → 0.10.0. Taken for a specific reason rather than as routine maintenance:
it is half the fix for the Android TLS failure Loopky was hitting in production.

rustls-platform-verifier hard-fails revocation checking on Android — Let's
Encrypt no longer publishes an OCSP responder, Android's PKIXRevocationChecker
only tries OCSP, and the crate's Kotlin half turns the resulting
CertPathValidatorException into `StatusCode.Revoked`:

    invalid peer certificate: Revoked
    ← CertPathValidatorException: Certificate does not specify OCSP responder

That surfaces as `HTTP transport error` and reaches Loopky users as "You're
offline". pubky 0.10 builds its **ICANN** client with webpki roots and
revocation off (`icann_tls_config_without_revocation_check`).

It does not cover pkarr's **relay** client, which is a separate client built
from reqwest's defaults and was still failing after this bump — see the
following commit, which is the other half. Neither alone made the device stop
erroring.

Merge notes:

- Source merged clean. One fork-only call site needed the 0.10 signature:
  `put_bytes` now threads a `client_id` through `signin`, matching what upstream
  did to `put`/`delete_file`/`sign_in`/`sign_up`/`start_auth_flow`.
- Every conflict was a generated artifact. Resolved by regenerating rather than
  picking a side — upstream's binaries are built from upstream's source and
  carry none of the fork's added functions. Android (4 ABIs, `llvm-strip`ped to
  match upstream), iOS xcframework and Swift, and the Python bindings are all
  rebuilt from this tree.
- `rustls-platform-verifier` stays a dependency: `cargo tree -i` still shows
  reqwest 0.13 pulling it in through pkarr 7.0, so `rustls_init.rs` is still
  load-bearing. Documented in Cargo.toml, along with the 0.10 version floor and
  the fact that the consuming app must also ship the crate's Kotlin AAR.

Not addressed here: `libpubkycore.so` still has a GNU_RELRO segment aligned to
0x1, so it is not 16 KB page-size compatible. Pre-existing and separate.
… verify

The pubky 0.10 bump in the previous commit was necessary and not sufficient. It
fixes revocation checking for the SDK's ICANN client only; pkarr builds its own
relay HTTP client from reqwest's defaults, which on Android still means
rustls-platform-verifier. Measured on-device after the bump: 8 more
`invalid peer certificate: Revoked` failures, every one immediately after

    pubky::actors::pkdns: Resolving homeserver for public key … via PKARR

so `_pubky.<key>` resolution that fell back to the relay kept dying, and Home
along with it. Resolutions the DHT answered succeeded, which is exactly why this
looked intermittent rather than total.

pkarr 7 exposes `ClientBuilder::reqwest_client`, and pubky 0.10 exposes
`.pkarr(..)` on its client builder, so the relay client can be handed the same
treatment upstream gave the ICANN one: bundled webpki roots, revocation off.
Reaching it means constructing through `PubkyHttpClient::builder()` +
`Pubky::with_client` instead of `Pubky::new()`/`Pubky::testnet()`.

Dropping revocation checking is upstream's own choice for this problem and the
trade is narrow here: these are relay lookups of public, signed pkarr records,
and the record's signature — not the transport — is what makes the answer
trustworthy.

reqwest goes 0.12 → 0.13 to match. The `reqwest::Client` handed to pkarr is only
type-compatible if it is literally the same crate version, and the fork used
reqwest directly in exactly one place (an admin HTTP call), so this also removes
a duplicate reqwest from the tree rather than adding one. webpki-roots is new,
pinned to the same major pubky uses so both paths trust the same anchors.

Verified on-device (Redmi Note 11, Android 13, release build), same session and
navigation each time:

    before #122          42 ClassNotFoundException, every TLS handshake failed
    after #122           0 ClassNotFound, 8 "Revoked", Home failed to load
    after 0.10 alone     still 8 "Revoked" — the relay client
    with this change     0 ClassNotFound, 0 TLS failures, 0 transport errors,
                         0 Loopky errors; session resolves in 1.8s, not 12

All bindings regenerated from this tree; Android libs `llvm-strip`ped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants