Skip to main content

Secure-FL in Rust

A type-safe port of the Secure-FL verifier and aggregation server. It speaks the same proof format and parameter representation as the Python package, so a Python client trained with PyTorch can submit to this server unchanged.

Scope: proof schema, commitments, norm enforcement, FedJSCM aggregation, and Groth16 verification. Training stays in Python — reimplementing PyTorch numerics in Rust would invalidate the existing benchmark results.

What changes vs. the Python server

Python Rust
dict[str, Any] + hand-written schema check ClientProof struct, malformed payloads fail to deserialize
verify_client_proof(...) -> bool, reason only in logs Result<(), Reject>, one typed variant per failure
snarkjs subprocess, 300 s timeout, temp files ark-groth16 verification in-process
json.loads → numpy, dtype inferred Tensor { dtype, shape, bytes }, dtype carried explicitly
per-round if tree returning False total functions returning reasons the caller can act on

Layout

rust/
├── securefl-core/          # no IO, no async
│   ├── tensor.rs           # dtype-preserving tensor + numpy-compatible math
│   ├── commit.rs           # state_hash (byte-identical to compute_hash), l2_norm
│   ├── proof.rs            # typed client proof payload
│   ├── verify.rs           # verification pipeline -> Reject
│   ├── fedjscm.rs          # momentum aggregation + trimmed mean
│   └── groth16.rs          # snarkjs vk/proof JSON -> arkworks verification
├── securefl-prover/        # native Groth16 proving from the existing .zkey
├── securefl-python/        # PyO3 extension (securefl_rust)
├── securefl-server/        # standalone axum round server
├── interop/                # fixture generator, HTTP smoke test, benchmark
└── fixtures/               # generated parity fixtures (checked in)

Wiring into the FL pipeline

There is no backend switch. secure_fl/backend.py's factories always return the Rust implementations:

Role Class
Proof verification, generation RustProofManager
FedJSCM aggregation RustFedJscmAdapter (exported as FedJSCMAggregator)
Stability heuristic StabilityMonitor (Rust)
make build-rust        # builds and installs src/securefl_rust.so
uv run secure-fl-server --config experiments/config.yaml

This covers the live Flower strategy (federation/server.py), the paper benchmark pipeline (benchmarks/pipeline.py, benchmarks/execution.py) and the attack benchmarks (benchmarks/attacks.py). Clients and training stay in PyTorch, so results remain comparable.

The Rust core owns the whole proof path: client delta-bound proofs, server aggregation proofs, both verifiers, aggregation, and the stability heuristic. Circom/snarkjs remain build-time tools only — make setup-zkp produces the circuit artifacts; nothing shells out at runtime.

The Python implementations of all four were removed once parity was proven.

Install as a wheel

make build-rust-wheel                            # rust/dist/securefl_core-<platform>.whl
uv pip install rust/dist/securefl_core-*.whl     # or: pip install ./rust/securefl-python

The wheel installs a top-level securefl_rust extension module, so it shares no files with the secure-fl wheel. It is built per platform and is not published to PyPI yet; make build-rust remains the editable-install path.

.github/workflows/wheels.yml (manual dispatch) builds all five targets — linux x86_64/aarch64, macOS arm64/x86_64, windows x64 — and uploads them as workflow artifacts.

release.yml publishes securefl-core alongside secure-fl on every tag, pinned to the same version. It needs a one-time trusted publisher on PyPI:

  1. Open https://pypi.org/manage/account/publishing/ and add a pending publisher with:
    • PyPI Project Name: securefl-core
    • Owner: krishantt
    • Repository name: secure-fl
    • Workflow name: release.yml
    • Environment name: release
  2. Nothing else. The GitHub environment release already exists (it is used by the secure-fl publish job).

Until that publisher exists, a release fails at publish-rust-core after secure-fl has been published; re-run the Release workflow once it is set up. The wheels.yml workflow still provides downloadable artifacts for testing.

Both packages publish through PyPI trusted publishing (OIDC), so PyPI attaches a PEP 740 attestation to every file — see the "Provenance" tab of secure-fl and securefl-core.

GitHub build attestations (actions/attest-build-provenance) are off: they need a public repo or a paid plan. Once the repo is public, add the step back to both publish jobs in release.yml along with attestations: write.

Protocol

GET  /v1/health                 -> {"status":"ok"}
PUT  /v1/model                  {tensors}       bootstrap or reset
GET  /v1/model                  -> {round, tensors, accepted_clients}
POST /v1/rounds/{r}/updates     {client_id, num_examples, tensors, proof}
POST /v1/rounds/{r}/aggregate   -> {round, tensors, server_proof?}

With --circuit-dir set, server_proof carries the aggregation Groth16 proof ({type, version, proof, public}), generated in-process and verifiable against the circuit's verification_key.json.

A tensor is {"dtype": "float32", "shape": [4,3], "data": "<base64 raw bytes>"}. Accepting updates returns {"accepted": true}; rejecting returns 422 with a typed reason in {"error": "..."}. verify order matches the Python server: proof type/version → replay guards → full state-dict hash → delta hash → norm bound → Groth16 delta-bound proof.

Run

cargo test                      # parity + crypto + unit tests

cargo run -p securefl-server -- \
  --bind 127.0.0.1:8080 \
  --vk ../src/secure_fl/proofs/client/build/delta_bound_vk.json \
  --learnable <(echo '[0,1,3,4]') \
  --max-norm 10 \
  --circuit-dir ../src/secure_fl/proofs/server

--learnable takes a JSON array of state-dict indices that are learnable parameters (BatchNorm buffers excluded), matching what the Python server gets from its BatchNorm mask. Use --learnable all when the model has no buffers.

Interop tests

# Regenerate fixtures from the Python implementation, then assert parity
../.venv/bin/python interop/gen_fixtures.py
cargo test

# Real server binary, real HTTP, real Groth16 proof
cargo build -p securefl-server && ../.venv/bin/python interop/smoke_http.py

# Run the Python suite against the Rust backend
make build-rust
uv run pytest tests/unit tests/e2e --no-cov

Historical measurements (the Python implementations have since been removed): docs/dev/RUST_END_TO_END_QUICK.md and docs/dev/RUST_BACKEND_BENCHMARK.md.

gen_fixtures.py imports the Python compute_hash, compute_parameter_norm and FedJSCMAggregator, and produces a real snarkjs Groth16 delta-bound proof plus a tampered copy. The Rust tests assert byte-identical commitments, matching aggregation output, native verification of the real proof, and rejection of both tampered proof points and tampered public signals.

The prover tests re-prove the committed input.json and assert the public outputs equal the snarkjs public.json, and that a proof built from unsatisfied inputs does not verify. They need the circuit build directory (make setup-zkp) and skip without it.

Deployment notes

  • No authentication. The server binds 127.0.0.1 by default; put it behind a reverse proxy with TLS and auth before exposing it.
  • Request bodies are capped at 256MB; a ResNet18 state dict is ~45MB.
  • Aggregation holds the round lock while proving, so a round blocks other requests for its duration (~30ms on the 400-public circuit).

Not ported (deliberately)

  • Training. No burn/candle/tch rewrite; clients keep using PyTorch and Flower. Numerics would diverge and the paper benchmarks would not transfer.
  • Flower clientapi transport. The standalone server covers a Python-free deployment; reimplementing Flower's reverse-RPC would move no round cost (verify → aggregate → prove is already Rust).
  • Textual TUI demo, CLI, dataset loading, benchmarks.

shortcut: aggregation crosses the PyO3 boundary by copying each tensor, so it lands within ~5–10% of the numpy implementation it replaced. Remove the copies with a borrowed-tensor API if that gap ever matters.

Metadata

Release files for securefl-core 26.10.147

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for securefl-core 26.10.147
File Actions
securefl_core-26.10.147-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details for securefl_core-26.10.147-cp312-abi3-win_amd64.whl
securefl_core-26.10.147-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.12 abi3 Linux glibc 2.17+ x86-64 Details for securefl_core-26.10.147-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
securefl_core-26.10.147-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.12 abi3 Linux glibc 2.17+ ARM64 Details for securefl_core-26.10.147-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
securefl_core-26.10.147-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details for securefl_core-26.10.147-cp312-abi3-macosx_11_0_arm64.whl
securefl_core-26.10.147-cp312-abi3-macosx_10_12_x86_64.whl CPython 3.12 abi3 macOS 10.12+ x86-64 Details for securefl_core-26.10.147-cp312-abi3-macosx_10_12_x86_64.whl

Total release size: 19.3 MB

Release files / securefl_core-26.10.147-cp312-abi3-win_amd64.whl

Download URL securefl_core-26.10.147-cp312-abi3-win_amd64.whl
Size 3.4 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
6d67e7f61e168092d5d6dbe3326f6be565e0607e5f0581eeec047840e8dec751
BLAKE2b-256 checksum
How to use checksums
203f38c2fad29577df22e330898fa6ed25b85a1b05e4f4c0ea6aa45d3ed88ba0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / securefl_core-26.10.147-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL securefl_core-26.10.147-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 4.1 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
9bd99dd3a6d00f9c7c079c7e54169e15b4cc20c4a8db9fd456a2033f248f4f78
BLAKE2b-256 checksum
How to use checksums
75f882eb714e2c9f360977511447f515a52aa8f216d750eab03cefacf8eef8a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / securefl_core-26.10.147-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL securefl_core-26.10.147-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 4.2 MB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
e734e7fb78ba51f89bdd9d0eb447460e0ef5778e2960608404c17cea3dfc6450
BLAKE2b-256 checksum
How to use checksums
c4e1b75eba896feb23915d0fb7e59bcd59324a6f56ad27ad95511268812b4584
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / securefl_core-26.10.147-cp312-abi3-macosx_11_0_arm64.whl

Download URL securefl_core-26.10.147-cp312-abi3-macosx_11_0_arm64.whl
Size 3.7 MB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
eed0abca1e4dc5178cb90196bd2e2d37599d0fc53f2378b8755366c25cf2c120
BLAKE2b-256 checksum
How to use checksums
bf148c188c44e0c00e2d91791a1cf6edad19310646fd93c78a93655be380d726
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / securefl_core-26.10.147-cp312-abi3-macosx_10_12_x86_64.whl

Download URL securefl_core-26.10.147-cp312-abi3-macosx_10_12_x86_64.whl
Size 3.8 MB
Tags CPython 3.12 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
8333c02a15e6032e02cf4a56369f8bec3cec8ec15321a2fd437d42345df04d2d
BLAKE2b-256 checksum
How to use checksums
264cb75d361e9594a8fd0eda8511b20d0a5eb6ebcacf038ac86a66f61cd16b7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for securefl-core 26.10.147

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page