Mobile SDKs
These mobile SDKs are maintained by zkmopro, a community project focused on bringing ZK proofs to mobile devices. While not part of the core Semaphore repository, they provide native mobile implementations of the Semaphore protocol.
Overview
The mobile SDKs enable native ZK proof generation on iOS, Android, React Native, and Flutter platforms, delivering significantly faster results than WASM-based alternatives.
All SDKs follow the same core workflow:
- Create an identity
- Create a group with members
- Generate a proof of group membership
- Verify the proof
Installation
- Swift (iOS)
- Kotlin (Android)
- React Native
- Flutter
For detailed setup and API reference, see the GitHub repository.
Xcode (Swift Package Manager)
- In Xcode, go to File > Add Package Dependencies
- Enter the repository URL:
https://github.com/zkmopro/SemaphoreSwift
Package.swift
dependencies: [
.package(url: "https://github.com/zkmopro/SemaphoreSwift", from: "0.1.0")
]
CocoaPods
pod 'Semaphore', :git => 'https://github.com/zkmopro/SemaphoreSwift'
For detailed setup and API reference, see the GitHub repository.
Add JitPack repository to your settings.gradle.kts:
dependencyResolutionManagement {
repositories {
maven { url = uri("https://jitpack.io") }
}
}
Add the dependency to your build.gradle.kts:
dependencies {
implementation("com.github.zkmopro:semaphore-kotlin:Tag")
}
Replace Tag with the desired version (e.g., 0.1.0).
For detailed setup and API reference, see the GitHub repository.
npm install https://github.com/zkmopro/SemaphoreReactNative
This package requires native modules. If you're using Expo, you'll need to use a development build or run npx expo prebuild to generate the native project files.
For detailed setup and API reference, see the GitHub repository.
Add to your pubspec.yaml:
dependencies:
semaphore:
git:
url: https://github.com/zkmopro/semaphore_flutter.git
Then run:
flutter pub get
Create an Identity
A Semaphore identity is required to join groups and generate proofs. See the identities guide for more details on the concept.
- Swift (iOS)
- Kotlin (Android)
- React Native
- Flutter
import Semaphore
// Create a random identity
let identity = Identity()
// Or create a deterministic identity from a private key
let identity = Identity(privateKey: privateKey)
// Access the commitment (public identifier)
let commitment = identity.commitment()
import com.example.semaphore.Identity
// Create a random identity
val identity = Identity()
// Or create a deterministic identity from a private key
val identity = Identity(privateKey)
// Access the commitment (public identifier)
val commitment = identity.commitment()
import { Identity } from "semaphore-react-native"
// Create a random identity
const identity = new Identity()
// Or create a deterministic identity from a private key
const identity = new Identity(privateKey)
// Access the commitment (public identifier)
const commitment = identity.commitment()
import 'package:semaphore/semaphore.dart';
// Create a random identity
final identity = await Identity.newInstance();
// Or create a deterministic identity from a private key
final identity = await Identity.newInstance(privateKey: privateKey);
// Access the commitment (public identifier)
final commitment = await identity.commitment();
Create a Group
A Semaphore group is a Merkle tree containing identity commitments. See the groups guide for more details.
- Swift (iOS)
- Kotlin (Android)
- React Native
- Flutter
import Semaphore
// Create a group with the identity's element
let group = Group(members: [identity.toElement()])
// Or create a group with multiple members
let group = Group(members: [identity1.toElement(), identity2.toElement()])
import com.example.semaphore.Group
// Create a group with the identity's element
val group = Group(listOf(identity.toElement()))
// Or create a group with multiple members
val group = Group(listOf(identity1.toElement(), identity2.toElement()))
import { Group } from "semaphore-react-native"
// Create a group with the identity's element
const group = new Group([identity.toElement()])
// Or create a group with multiple members
const group = new Group([identity1.toElement(), identity2.toElement()])
import 'package:semaphore/semaphore.dart';
// Create a group with the identity's element
final group = await Group.newInstance(members: [await identity.toElement()]);
// Or create a group with multiple members
final group = await Group.newInstance(members: [
await identity1.toElement(),
await identity2.toElement()
]);
Generate a Proof
Generate a ZK proof that demonstrates group membership without revealing your identity. See the proofs guide for more details on scopes and messages.
- Swift (iOS)
- Kotlin (Android)
- React Native
- Flutter
import Semaphore
let proof = try generateSemaphoreProof(
identity: identity,
group: group,
message: "Hello World",
scope: "app-scope",
merkleTreeDepth: 16
)
import com.example.semaphore.generateSemaphoreProof
val proof = generateSemaphoreProof(
identity = identity,
group = group,
message = "Hello World",
scope = "app-scope",
merkleTreeDepth = 16.toUShort()
)
import { generateSemaphoreProof } from "semaphore-react-native"
const proof = await generateSemaphoreProof(
identity,
group,
"Hello World",
"app-scope",
16
)
import 'package:semaphore/semaphore.dart';
// Convert identity and group to Arc references for proof generation
final arcIdentity = await identity.toArc();
final arcGroup = await group.toArc();
final proof = await generateSemaphoreProof(
identity: arcIdentity,
group: arcGroup,
message: "Hello World",
scope: "app-scope",
merkleTreeDepth: 16,
);
The merkleTreeDepth parameter determines the maximum group size (2^depth members). A depth of 16 supports up to 65,536 members. Match this value with your on-chain group configuration.
Verify a Proof
Verify that a proof is valid. This can be done locally on the device or on a server.
- Swift (iOS)
- Kotlin (Android)
- React Native
- Flutter
import Semaphore
let isValid = try verifySemaphoreProof(proof: proof)
import com.example.semaphore.verifySemaphoreProof
val isValid = verifySemaphoreProof(proof)
import { verifySemaphoreProof } from "semaphore-react-native"
const isValid = await verifySemaphoreProof(proof)
import 'package:semaphore/semaphore.dart';
final isValid = await verifySemaphoreProof(proof: proof);
For on-chain verification, you can send the proof to your backend and use the Semaphore smart contract's validateProof function. See the proofs guide for details.
Performance
By proving natively, the mobile SDKs deliver significantly faster proof generation performance than WASM-based alternatives.
The benchmarks below were measured using the Semaphore-32 circuit with rapidsnark, which supports groups with up to 2^32 members. For detailed performance comparisons across different devices, proving systems, and circuits, see the performance section of zkmopro docs.
| Platform | Device | Proof Generation Time |
|---|---|---|
| iOS | iPhone 16 Pro (2024) | ~143 ms |
| Android | Samsung S23 Ultra (2023) | ~166 ms |
Resources
- iOS (Swift): https://github.com/zkmopro/SemaphoreSwift
- Android (Kotlin): https://github.com/zkmopro/SemaphoreKotlin
- React Native: https://github.com/zkmopro/SemaphoreReactNative
- Flutter: https://github.com/zkmopro/semaphore_flutter
- Rust Bindings: https://github.com/vivianjeng/semaphore-bindings
- zkmopro Documentation: https://zkmopro.org/docs/intro