HMAC-only JWT provider to shrink binaries - #1171
Merged
Merged
Conversation
Replace jsonwebtoken's rust_crypto backend with an in-crate HMAC-only CryptoProvider (HS256/384/512). LiveKit access tokens are HS256 and the access_token API is HS256-hardcoded (jsonwebtoken isn't re-exported), so the dropped RSA/EC/EdDSA algorithms were never reachable. Installed as the process-global provider on first sign/verify. Shrinks the shipped binaries ~25-29% (also benefits livekit-ffi/livekit): - RustLiveKitUniFFI ios-arm64 framework: ~900 -> 672 KiB - livekit-uniffi android arm64-v8a .so: ~1157 -> 816 KiB Tighten CI size guards to 5% over the measured real artifacts: - SPM_SIZE_LIMIT_BYTES: 1 MiB -> 723467 - ANDROID_SIZE_LIMIT_BYTES: 1.5 MiB -> 877918 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aarch64-apple-tvos and aarch64-apple-visionos (+ -sim) are now Tier 2 with prebuilt std (tvOS since 1.84; visionOS after), so cargo-swift builds them on stable. Add them to the regular target list and remove the nightly + rust-src install. Verified by a full xcframework build on the pinned 1.96.0: all slices use prebuilt std (no -Zbuild-std, no recompiled core/std). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
ChangesetThe following package versions will be affected by this PR:
|
Fixes the License Check (missing Apache header on the new file) and Rust Formatting CI jobs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
davidliu
approved these changes
Jun 16, 2026
2 tasks
pblazej
added a commit
that referenced
this pull request
Jul 30, 2026
…1300) - build-android-*: cargo-make's `extend` replaces the parent env map rather than merging it, so `env = { TARGET = ... }` silently dropped ANDROID_RELEASE_FLAG and RUSTFLAGS — `--profile release` produced debug .so files and android-copy-jniLibs found nothing in target/*/release. Derive the flag from CARGO_MAKE_PROFILE in the script instead. - android-bindgen-kotlin: TARGET leaks across cargo-make tasks, so bindgen-kotlin's `build` dependency cross-compiled for Android with the host linker ("cannot find -llog"). Pin TARGET back to the host triple and keep symbols, which library-mode bindgen needs on Linux. - Raise both size gates to measured values: ios-arm64 is 1088 KiB and arm64-v8a 1174 KiB, having grown past the limits set in #1171 when the data-track UniFFI surface landed in #1034. - Check out inputs.tag_name in both reusable workflows; workflow_dispatch was building the dispatch ref (main) rather than the requested tag. ### Before you submit your PR Make sure the following is true before submitting your PR: - [ ] I have read the [contributing guidelines](https://github.com/livekit/rust-sdks/blob/main/CONTRIBUTING.md) and validated that this PR will be accepted. - [ ] I have read and followed the principles regarding breaking changes, testing, and code quality. ### PR description Describe the changes in this PR. Explain what the PR is meant to solve and how to reproduce the issue in the first place. ### Breaking changes If this PR introduces breaking changes, list them here and document the rationale for introducing such a change. ### MSRV If the PR modifies the crate's MSRV (Minimum Supported Rust Version), document it here. ### Testing Ideally, unit test the code you add, but ensure you're not repeating existing test cases. Use as many already written scaffolding, utilities as possible; write your own, when needed. If external services, APIs, tokens are required (e.g., running an LK server instance), provide the necessary information. Make sure your tests perform useful, context-aware assertions and do not simply emulate "happy paths". ### Async We want the project to be runtime-agnostic, so please reuse what's already in [livekit-runtime](https://github.com/livekit/rust-sdks/blob/main/livekit-runtime/) and feel free to add anything missing. It's ok to use Tokio directly, when writing unit tests, if necessary. When testing, do not use artificial delays for the state to "catch up"; instead, respect the event flow and subscribe properly using channels or other mechanisms. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
LiveKit access tokens are HS256, yet
livekit-apipulled jsonwebtoken's fullrust_cryptobackend (RSA/EC/EdDSA). This swaps it for a minimal in-crate HMACCryptoProvider, dropping ~200 KiB of unreachable crypto from every shippedbinary. No public API or behavior change.
Also removes the now-obsolete nightly/
build-stdCI step for tvOS/visionOS —both are Tier 2 with prebuilt std now.
Size impact
RustLiveKitUniFFIiOS arm64 frameworkliblivekit_uniffiAndroid arm64-v8a.soiOS bloaty diff is almost entirely code:
__TEXT,__text−186 KiB,__TEXT,__const(EC/RSA constant tables) −44 KiB.
livekit-ffi/livekitbenefit too.Size guards tightened to 5% over the measured artifacts: iOS
SPM_SIZE_LIMIT_BYTES1 MiB →723467; AndroidANDROID_SIZE_LIMIT_BYTES1.5 MiB →
877918.Why a custom provider
jsonwebtoken 10 resolves its backend through a process-global
CryptoProvider,and
new_signer/new_verifierstatically reference every algorithm — so thelinker can't dead-strip RSA/EC/EdDSA; only feature removal works. The
EncodingKey/DecodingKey::try_get_hmac_secret()accessors and theJwtSigner/JwtVerifiertraits are public, so an HS256/384/512 provider is~40 lines, installed idempotently on first sign/verify.
Alternatives considered
livekit-uniffirequestslivekit-apiwithoutrust_crypto): doesn't work — cargo compileslivekit-apionce with theworkspace-union of features, and
livekit/livekit-ffirequest the defaults,so
rust_cryptostays linked regardless.livekit-uniffias its own workspace: excluding it from the root workspacewould isolate feature resolution, making a per-crate gate work without
changing the published
livekit-apidefault. Rejected — a larger structuralchange (explicit path deps instead of
workspace = true, separateCargo.lock) for no extra savings over the default swap, which is safe heresince everything is HS256.
services-tokio/reqwest, gateos_info/device-info, trimlivekit-protocol: ~0 binary impact — bloaty shows these are alreadydead-stripped (nothing in the token path references them).
build-stdfor iOS: ~27 KiB more (the__eh_frameunwinding tables fromthe prebuilt panic=unwind std), but needs nightly for the primary slice.
Deferred.
Safety
re-exported, so RSA/EC/EdDSA were never reachable — removing them changes no
public behavior.
Onceat allthree entry points (
to_jwt,verify,from_unverified) before anyencode/decode. Unsupported algorithms return a cleanErr, never a panic.install_default()could conflict with anapp that separately uses jsonwebtoken-10 for non-HS256 JWTs in the same
process — narrow, and documented in
jwt_provider.rs.Validation
cargo test -p livekit-apipasses (sign / verify / unverified-decode).livekit-fficompiles unchanged.prebuilt std (no
-Zbuild-std, no recompiledcore/stdon any slice).🤖 Generated with Claude Code