An iOS prototype consolidating all PQC engineering artifacts produced in the thesis Analysis of Transition to Post-Quantum Cryptography on Mobile Platforms. It serves as a practical reference for developers and researchers undertaking PQC migration on iOS.
⚠️ Note: This prototype is intended for research and prototyping purposes only. It is not recommended for use in production systems.
Note: Android artifacts (JNI library, Jetpack Benchmark suite, build scripts, TVLA pipeline) are maintained in the PqcMobileToolkit repository.
The prototype integrates two PQC backends side-by-side:
- liboqs — a direct Swift/C bridge to the Open Quantum Safe liboqs static library, providing access to the full algorithm suite across security levels 3 and 5.
- CryptoKit (iOS 26+) — Apple's native framework, supporting ML-KEM and ML-DSA with hardware-backed key storage and
integrityCheckedRepresentationon secret values.
Both backends conform to shared KemManaging and SigManaging protocols, allowing the app and benchmark suite to switch between them without code duplication.
- Prototype application — SwiftUI app demonstrating end-to-end PQC integration with both liboqs and CryptoKit backends. Supports runtime library switching, algorithm selection, and displays timing measurements per operation.
- Benchmark suite — XCTest performance harness (
PqcBenchmarkTests) measuring key generation, encapsulation/decapsulation (KEM), and signing/verification (DSA) for all algorithm and library combinations at 10 000 iterations usingXCTClockMetric. - Compilation script — Shell script cross-compiling liboqs 0.15.0 (with OpenSSL 3.5.5) for iOS using CMake and the
ios-cmaketoolchain.
iOSPqcDemoApp/
├── iOSPqcDemoApp/ # Application source
│ ├── liboqs-ios/ # liboqs Swift/C wrapper layer
│ │ ├── OqsKemManager.swift # KEM operations (keygen, encaps, decaps)
│ │ ├── OqsSignatureManager.swift # DSA operations (keygen, sign, verify)
│ │ ├── PqcConstants.swift # Algorithm identifier enums & CryptoKit mapping
│ │ └── model/ # KemKeypair, SigKeypair, KemEncapsulationResult, OqsError, Utils
│ ├── crypto-kit/ # CryptoKit wrapper layer (iOS 26+)
│ │ ├── CryptoKitKemManager.swift
│ │ └── CryptoKitSignatureManager.swift
│ ├── ContentView.swift # SwiftUI UI
│ ├── PqcViewModel.swift # ObservableObject driving all crypto flows
│ ├── PqcLibrary.swift # Library selector enum with availability checking
│ └── iOSPqcDemoAppApp.swift # App entry point
├── iOSPqcDemoAppTests/ # XCTest benchmark suite
│ ├── PqcBenchmarkTests.swift # Performance benchmarks (liboqs + CryptoKit)
│ └── iOSPqcDemoAppTests.swift
├── iOSPqcDemoAppUITests/ # UI test targets
├── include_liboqs/oqs/ # Pre-compiled liboqs C headers (27 files)
├── libs/
│ └── liboqs.a # Pre-compiled liboqs static library (arm64)
├── scripts/
│ └── compile_liboqs_ios.sh # liboqs + OpenSSL iOS cross-compilation script
├── Bridging-Header.h # Swift/C bridging header for liboqs
└── iOSPqcDemoApp.xcodeproj
| Module | Description |
|---|---|
| liboqs-ios | Swift wrappers over the liboqs C static library. OqsKemManager and OqsSignatureManager handle unsafe memory management, OQS_KEM/OQS_SIG lifecycle, and buffer size validation. Accepts any algorithm name string supported by the linked liboqs build. |
| crypto-kit | Thin wrappers conforming to KemManaging / SigManaging using MLKEM768, MLKEM1024, MLDSA65, and MLDSA87 from CryptoKit. Requires iOS 26+. Key material is stored via integrityCheckedRepresentation. |
| app | SwiftUI prototype demonstrating end-to-end KEM and DSA flows. Supports runtime switching between liboqs and CryptoKit, with per-operation wall-clock timing displayed in a scrollable log view. |
| iOSPqcDemoAppTests | XCTest benchmark suite measuring each operation independently (12 liboqs tests, 12 CryptoKit tests) using XCTClockMetric at 10 000 iterations. Median latency is derived from the per-sample values in the .xcresult bundle. |
| scripts/compile_liboqs_ios.sh | Bash script that clones liboqs 0.15.0, optionally builds OpenSSL 3.5.5, then cross-compiles a static liboqs.a for iOS using CMake and the ios-cmake toolchain. Outputs headers and the static library into include_liboqs/ and libs/. |
| Algorithm | Variants | NIST Level |
|---|---|---|
| ML-KEM | 768, 1024 | 3, 5 |
| HQC | 192, 256 | 3, 5 |
| FrodoKEM | 976-AES, 976-SHAKE, 1344-AES, 1344-SHAKE | 3, 5 |
| BIKE | L3, L5 | 3, 5 |
| Algorithm | Variants | NIST Level |
|---|---|---|
| ML-KEM | 768, 1024 | 3, 5 |
| Algorithm | Variants | NIST Level |
|---|---|---|
| ML-DSA | 65, 87 | 3, 5 |
| SLH-DSA | SHA2/SHAKE, 192f/192s, 256f/256s | 3, 5 |
| Falcon | 1024 | 5 |
| MAYO | 3, 5 | 3, 5 |
| CROSS | RSDP/RSDPG variants | 3, 5 |
| UOV | Ip, Is, III | 3, 5 |
| Algorithm | Variants | NIST Level |
|---|---|---|
| ML-DSA | 65, 87 | 3, 5 |
// Key generation
let kem = try OqsKemManager(algorithm: "ML-KEM-768")
let keypair = try kem.generateKeypair()
// Encapsulation (sender side)
let result = try kem.encapsulate(publicKey: keypair.publicKey)
// result.ciphertext → send to recipient
// result.sharedSecret → use as symmetric key
// Decapsulation (recipient side)
let sharedSecret = try kem.decapsulate(
ciphertext: result.ciphertext,
secretKey: keypair.secretKey
)// Key generation
let sig = try OqsSignatureManager(algorithm: "ML-DSA-65")
let keypair = try sig.generateKeypair()
// Signing
let message = Data("Hello, PQC".utf8)
let signature = try sig.sign(message: message, secretKey: keypair.secretKey)
// Verification
let isValid = try sig.verify(
message: message,
signature: signature,
publicKey: keypair.publicKey
)let kem = CryptoKitKemManager(algorithm: .mlKem768)
let keypair = try kem.generateKeypair()
let result = try kem.encapsulate(publicKey: keypair.publicKey)
let sharedSecret = try kem.decapsulate(
ciphertext: result.ciphertext,
secretKey: keypair.secretKey
)let sig = CryptoKitSignatureManager(algorithm: .mldsa65)
let keypair = try sig.generateKeypair()
let message = Data("Hello, PQC".utf8)
let signature = try sig.sign(message: message, secretKey: keypair.secretKey)
let isValid = try sig.verify(
message: message,
signature: signature,
publicKey: keypair.publicKey
)A pre-compiled liboqs.a is already included in libs/. To rebuild it:
cd scripts
./compile_liboqs_ios.shThe script requires cmake, ninja, git, curl, and xcodebuild. It targets the iOS arm64 architecture using the ios-cmake toolchain and optionally links OpenSSL for AES hardware acceleration.
This project is licensed under the MIT License — see LICENSE for details.
The project bundles a pre-compiled static library from liboqs, which is primarily MIT-licensed but includes third-party components under various open-source licenses (Apache 2.0, BSD 3-Clause, CC0, and others). See the liboqs LICENSE and liboqs README for full details.
- Xcode 16+
- iOS 15.0+ deployment target (liboqs backend)
- iOS 26.0+ for CryptoKit PQC backend
- Target architecture:
arm64(iOS device) - liboqs 0.15.0