Skip to content
Oumuamua Labs

Proving Stack · 02 Ship to the device

ZK Toolkit for iOS & Android

Add zero-knowledge proofs to iOS and Android apps: on-device proving keeps private data on the phone, and one async Swift or Kotlin call returns the proof.

hekate-mobile 0.3.0 AGPL-3.0-only source
import Hekate

let output = try await MyProver.prove(
    inputs: myInputs,
    priority: .userInitiated
)
SwiftPM · async/await Hekate Swift
import dev.oumuamua.hekate.prove
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

viewModelScope.launch {
    val output = MyProver.prove(inputs, Dispatchers.Default)
}
Gradle · coroutines Hekate Kotlin

What you get

Client-side proving for mobile apps: a zero-knowledge proof is made on the user’s own iPhone or Android phone. The private data stays on the device, and your server receives a proof it can check without seeing any of it.

You write the statement once in Rust. Two build commands turn that crate into two .xcframework bundles and an .aar with the Hekate prover inside. The app team calls one async function in Swift or one suspend function in Kotlin and gets the proof back.

The API the app calls is made of your own types. No field element, trace or transcript appears in Swift or Kotlin.

Private data stays on the device

On-device proving: the prover runs inside your app’s process. There is no remote prover, no upload, no key escrow and no trusted setup.

Post-quantum signatures from secure hardware

The example app signs with an ML-DSA (Dilithium) key that never leaves the iPhone’s Secure Enclave and proves the signature is valid without revealing it. A second statement proves an RSA-2048 signature.

A prover the user can stop

Task.cancel() in Swift and Job.cancel() in Kotlin reach the Rust prover, which stops at its next poll.

A panic is an error

A panic in your code or in the prover comes back as a typed error on the Swift or Kotlin side, and the app keeps running.

Measured on real iPhones

The example apps sign with a key the phone made, prove an ML-DSA or an RSA-2048 signature in zero knowledge and report proving time, proof size and peak memory. Mobile ZK Benchmarks

From a Rust crate to an app

iOS

cargo xtask ios-build

Writes two .xcframework bundles, yours and the Hekate prover’s, for devices and Apple-silicon simulators on iOS 16 and up, and the Swift bindings file the app compiles.

Android

cargo xtask android-build

Writes one .aar with your library, the Hekate prover and the generated Kotlin bindings, for arm64-v8a on Android API 26 and up.

Where the prover comes from

The build fetches the prover binary for each target during cargo build and checks its SHA-256, its Ed25519 signature and its ML-DSA-65 signature against keys pinned in the crate. A mismatch fails the build. Nothing on the device checks those signatures again: the binary ships inside your app and is covered by your own Apple and Play signing.

SDKs