# Mobile ZK Benchmarks

> Mobile zero-knowledge proof benchmarks: proving time, proof size and peak memory for ML-DSA (Dilithium), RSA-2048, Keccak-256 and SHA-256 proofs.

- URL: https://oumuamua.dev/mobile/benchmarks
- Published: 2026-10-12T18:30:17+07:00
- Updated: 2026-10-13T09:07:15+07:00

On-device proving, measured on real phones. These figures come from the example apps in the
[`hekate-mobile` repository](https://github.com/oumuamua-labs/hekate-mobile/tree/main/examples). An app signs a
message with a key the phone made, proves the signature is valid without revealing it, verifies the zero-knowledge
proof on the phone and reports what that cost. One signature is post-quantum, ML-DSA (Dilithium), and one is
RSA-2048. The app also proves that it knows a message with a given Keccak-256 or SHA-256 digest.

## Performance

Measured on an iPhone 14 Pro Max and an iPhone 11 Pro Max, the signed constant-time prover 0.15.0 with hekate 0.37.0. Zero knowledge is on (`Config::default()`, 100-bit soundness). Each figure is the best of three proofs. The signature proofs ran with the phone on battery, the thermal state nominal and Low Power Mode off. The Keccak-256 proofs ran on battery and the SHA-256 proofs on the charger. Peak footprint is the app's highest physical footprint since launch, over those three proofs. iOS versions may count it differently: read each phone's figure on its own. The iPhone 11 Pro Max ran iOS 18, which cannot sign ML-DSA.

### iPhone 14 Pro Max, iOS 26.7.1

| Proof | Witness | Prove | Whole call | Verify | Proof size | Peak footprint |
|:---|:---|:---|:---|:---|:---|:---|
| ML-DSA-65, key in the Secure Enclave | 190.4 ms | 1339.7 ms | 1546.4 ms | 26.2 ms | 1,577 KiB | 156 MiB |
| RSA-2048 PKCS#1 v1.5 | 89.9 ms | 484.6 ms | 594.4 ms | 20.7 ms | 1,808 to 1,814 KiB | 252 MiB |

### iPhone 11 Pro Max, iOS 18.6.2

| Proof | Witness | Prove | Whole call | Verify | Proof size | Peak footprint |
|:---|:---|:---|:---|:---|:---|:---|
| RSA-2048 PKCS#1 v1.5 | 150.0 ms | 832.0 ms | 1014.8 ms | 34.1 ms | 1,811 to 1,815 KiB | 187 MiB |

### Hashing, iPhone 14 Pro Max, iOS 26.7.1

| Proof | Prove | Verify | Proof size | Peak footprint |
|:---|:---|:---|:---|:---|
| Keccak-256 of a 1 KiB message | 59 ms | 5.3 ms | 353 to 357 KiB | 46 MiB |
| Keccak-256 of a 174 KiB message | 770 ms | 8.8 ms | 858 to 863 KiB | 120 MiB |
| Keccak-256 of a 5.44 MiB message | 26.7 s | 28 ms | 3,529 to 3,531 KiB | 1,852 MiB |
| SHA-256 of a 1 KiB message | 72 ms | 6.5 ms | 439 to 441 KiB | 56 MiB |
| SHA-256 of a 127.9 KiB message | 1.03 s | 10 ms | 1,034 KiB | 140 MiB |

## What the columns mean

- Witness is the time Rust takes to turn the signature into the execution trace, before the prover starts.
- Prove is the time inside the prover. The [Hekate benchmarks](https://oumuamua.dev/hekate/benchmarks) cover this phase alone.
- Whole call is what the app waits for one proof: the input checks, both phases and the FFI.
- Verify is the time inside the verifier, run on the phone with the same crate.
- Proof size is the serialized proof. It differs by a few KiB from run to run.
- Peak footprint is the most memory the app has held since it started.

## What each proof states

The [RSA-2048](https://oumuamua.dev/primitives/signatures/rsa) proof states that its maker holds a message and a PKCS#1 v1.5 signature
on it that verifies under a public modulus. The message and the signature stay hidden.

The [ML-DSA-65](https://oumuamua.dev/primitives/signatures/mldsa) proof states that its maker holds a signature on a public message
that verifies under a key whose hash is public. The public key and the signature stay hidden, and the private key
never leaves the Secure Enclave.

Neither signature proof shows that its maker holds the private key. Any signature the key ever released will do. A
verifier that wants a fresh one picks the message itself, which the ML-DSA statement allows because its message is
public.

The [Keccak-256](https://oumuamua.dev/primitives/hashing/keccak) and [SHA-256](https://oumuamua.dev/primitives/hashing/sha2) proofs state that their maker
knows a message of a public length whose digest is public. The message stays hidden. Keccak-256 pads with the byte
`0x01`, as Ethereum does. SHA3-256 pads with `0x06` and gives another digest.

## Run it on your phone

Four commands fetch the repository, build the frameworks and open the iPhone project:

```bash
git clone https://github.com/oumuamua-labs/hekate-mobile
cd hekate-mobile/examples/prover
cargo xtask ios-build --unsigned
open ../ios/HekateExamples.xcodeproj
```

Pick your team in Xcode, select the phone and run. If Xcode cannot register the bundle identifier, change it: Apple
gives each one to a single team. For a figure worth keeping, start the app from the Home screen and run one statement
per launch: the peak footprint counts from the start of the app. The
[examples README](https://github.com/oumuamua-labs/hekate-mobile/blob/main/examples/README.md) has the Android
steps and the full list of report rows.