SDK Overview
The FidesInnova zk-IoT ZKP SDK is a library that enables IoT device firmware to generate zero-knowledge proofs (zk-SNARKs) on-device. It is the component that makes an ordinary IoT device a cryptographically trustworthy zk-Device.
The SDK implements:
- Witness generation — computing all intermediate values in the firmware execution trace
- R1CS satisfaction checking — verifying the witness satisfies the compiled circuit constraints
- Groth16 proof construction — computing the three elliptic curve points that form the proof
- Proof serialization — encoding the proof as a compact byte array for MQTT transmission
The SDK is fully open source under the MIT license. All source code is available at github.com/FidesInnova.
Performance reference (from IEEE paper): Proof generation ≈694ms (Groth16), verification ≈19ms, proof size ≈200 bytes on ESP32-class hardware. Plonk proof system is also supported: ≈777ms generation, ≈22ms verification.
ESP32 (C++)
Espressif ESP32 and ESP32-S3. The primary reference platform — all FidesInnova reference hardware (E-card V2, zk-MultiSensor, MiniSensor) is built on ESP32. Arduino IDE and ESP-IDF both supported.
ARM Cortex-M (C++)
STM32, nRF52, SAMD51, and compatible MCUs with at least 512KB flash and 256KB RAM. Bare metal and RTOS (FreeRTOS, Zephyr) supported.
RISC-V (C++)
ESP32-C3, ESP32-C6, and compatible RISC-V MCUs. Growing platform support as RISC-V adoption increases in IoT silicon.
Linux (Rust)
Raspberry Pi, NVIDIA Jetson, BeagleBone, and any armv7/aarch64/x86_64 Linux system. The Rust SDK also supports WebAssembly for browser-based verification.
Minimum Requirements
Flash: 512KB (proof generation tables). RAM: 128KB (witness computation buffer). For tighter MCUs, use the SDK's low-memory mode (trades speed for memory: ~2s proof time, 64KB RAM).
Not Yet Supported
Deeply constrained MCUs (Arduino Uno/Nano, 8-bit AVR). These lack sufficient flash for the proving key tables. Planned: proof offloading to a gateway node for these devices.
C++ SDK Integration (ESP32 Example)
Step-by-step integration for an ESP32 project using Arduino IDE or PlatformIO:
1
Install the SDK
# PlatformIO: add to platformio.ini
lib_deps = https://github.com/FidesInnova/zkp-sdk-cpp.git
# Arduino IDE: Library Manager → search "FidesInnova ZKP"
2
Initialize the SDK
#include "fidesinnova_zkp.h"
FidesZKP zkp;
void setup() {
// Initialize with proving key stored in flash partition
if (!zkp.begin(PROVING_KEY_PARTITION)) {
Serial.println("ZKP init failed");
}
}
3
Generate a Proof
void loop() {
float temp = sensor.readTemperature();
uint32_t ts = (uint32_t)time(nullptr);
// Build witness input
ZKPInput input = { .temperature = (int32_t)(temp * 100), .timestamp = ts };
// Generate proof (~694ms blocking call)
ZKPProof proof;
if (zkp.generateProof(input, &proof)) {
// Serialize and publish via MQTT
uint8_t buf[256]; size_t len;
zkp.serializeProof(proof, buf, &len);
mqttPublishWithProof(temp, buf, len);
}
delay(30000); // 30 second measurement interval
}
Rust SDK Integration (Linux Example)
# Cargo.toml
[dependencies]
fidesinnova-zkp = "0.3"
tokio = { version = "1", features = ["full"] }
// main.rs
use fidesinnova_zkp::{ZKP, ProofInput};
#[tokio::main]
async fn main() {
let zkp = ZKP::new("./proving_key.bin").await.unwrap();
let input = ProofInput { temperature: 2240, timestamp: now_unix() };
let proof = zkp.generate_proof(input).await.unwrap();
let bytes = proof.serialize();
// publish bytes + reading via MQTT...
}
AI ZKP Integration Agent
The ZKP Integration Agent is an AI tool that automates SDK integration into your existing firmware:
- Upload your firmware source code (or provide a GitHub URL)
- The agent analyzes your code structure and identifies sensor reading points
- It generates the modified firmware with ZKP calls inserted at the correct locations
- It generates a
platformio.ini or Cargo.toml with SDK dependency added
- Review the diff, approve, and download the modified firmware
Security note: The agent processes your code server-side. For sensitive commercial firmware, use the agent on a sanitized test version and manually apply the identified integration pattern to your production code.
Proof Generation Flow
Understanding the internal flow helps with debugging and optimization:
1
Input Preparation (~5ms)
Sensor readings are converted to integer field elements (multiply floats by 100 or 1000 to preserve decimal precision as integers). Timestamp and device ID are included in the witness input.
2
Witness Computation (~180ms)
The SDK evaluates the compiled circuit on the inputs, computing all intermediate wire values. This is the most memory-intensive phase — the witness buffer is allocated in RAM.
3
Proof Computation (~500ms)
Three elliptic curve multi-scalar multiplications (MSM) on BN-128 curve compute the proof points A, B, C. This is the most CPU-intensive phase — the proving key (stored in flash) is streamed in chunks during this phase to minimize RAM usage.
4
Serialization (~2ms)
The three curve points are serialized to ~200 bytes using compressed point representation. The proof is ready for MQTT transmission.
Performance Optimization
- Async proof generation — on RTOS platforms (FreeRTOS, Zephyr), run proof generation in a background task so sensor polling continues during the ~700ms proof computation
- Proof batching — on high-frequency sensors (readings every second), generate a proof for every Nth reading (N=10 for 10-second effective proof frequency) to reduce CPU load without losing verifiability
- Low-memory mode — if RAM is below 128KB, enable
zkp.setLowMemoryMode(true) — proof generation takes ~2s but only uses 64KB RAM
- Flash partition sizing — the proving key requires ~400KB of flash storage. Ensure your partition table allocates a dedicated NVS partition of at least 512KB
- CPU frequency — on ESP32,
setCpuFrequencyMhz(240) during proof generation reduces time by ~35% vs. 160MHz
Troubleshooting Common Issues
❌ "Proving key not found"
The proving key must be flashed to the device separately from the firmware binary. Use the FidesInnova CLI: fi-cli flash-key --port /dev/ttyUSB0
❌ "Witness computation failed"
Ensure all input values are within the circuit's valid range. The circuit expects integers in the range [0, 2³²]. Float readings must be scaled to integers before passing to generateProof().
❌ Proof rejected by Node
Mismatch between the device's proving key and the Node's verification key. Both must be from the same trusted setup ceremony. Re-download and re-flash the proving key from your Node dashboard.
❌ Out of memory crash
Enable low-memory mode or increase the heap allocation for the zkp object. On ESP32 with PSRAM, the SDK automatically uses external RAM for the witness buffer — enable PSRAM in menuconfig.