Zero-knowledge proofs enable a prover to convince a verifier that a statement is true, without revealing the underlying witness data. This primitive naturally lends itself to privacy-preserving systems, where hiding the witness prevents the verifier from learning sensitive information. That said, zero-knowledge proofs can also be used in systems where the witness is not necessarily confidential but is not readily available to the verifier. One such use case is image provenance, where signed images are transformed before being distributed. Since the original image is not available to the user, the digital signature cannot be verified without a zero-knowledge proof. In this use case, zero-knowledge proofs enable verification of the authenticity of the image's source, the integrity of the image contents, and that only permitted transformations were applied. In this work we present an end-to-end prototype system that implements this provenance framework and several optimizations. One of our key optimizations is a packing scheme for reducing the number of Poseidon sponge absorb and permutation operations by ~32x. We also show that this packing scheme reduces median prover runtime by ~40x and verifier runtime by ~22x. We also introduce a chain of trust that removes digital signature verification from the circuit. Finally, we introduce custom PNG chunks that embed the required information in the captured images.
- Download and clone the repository
- Edit
png_editor.pyto point to an RGB PNG file in\images - Run
python png_editor.py - Edit
main.rsto the edited image path - Run
cargo build --releasefrom the top-level directory - Run
cargo run --releasefrom the top-level directory
The Raspberry Pi 4 used as the signing camera has the following specifications:
- CPU: Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit
- RAM: 8 GB LPDDR4-3200 SDRAM
- Disk: 128 GB MicroSD
- Raspberry Pi Camera Module v2
The proofs are computed by a Lenovo Thinkpad X1 with the following specifications:
- CPU: 12th Gen Intel i9-12900H
- Memory: 16 GB
- OS: Ubuntu 22.04.4 (in WSL2)
- rustc: 1.87.0
- Kernel: x86_64 Linux 6.6.87.2-microsoft-standard-WSL2
The primary libraries used by the implementation are listed below:
- halo2_proofs v0.3.2
- Python v3.14
- halo2curves v0.9.0
- image v0.25.9
- rand v0.8
- ff v0.13.1
- crc32fast v1.5.0
- secp256k1 v0.31.1
- The prototype and the hardware it was run on do not scale well enough to handle images of significant size. Memory is the main bottleneck and memory usage needs to be optimized in future work.
- The prototype relies on transferring the verifying key to the verifier out-of-band. Thus, security is based on an assumption of no swapping or corruption during that process.
- The only transformation implemented by the prototype is greyscale.
- The prototype relies on the signing camera and circuit using the same field, hash function, and parameters.
- Currently, there is no mitigation against an adversary injecting additional hASh, sIGn, or eXIf chunks.
- Implementing PKI or a public blockchain to publish verifying keys, removing the out-of-band security assumption from the current prototype.
- Improving prover efficiency using folding / IVC with a system like Nova.
- Improving prover efficiency by condensing Poseidon computations into a scheme that uses fewer rows and implementing Poseidon2.
- Implementing other common transformations such as cropping, minimal blurring, and resizing.
- Implementing an optional protocol for the camera and circuit to negotiate alternate hash functions and parameters.
- Researching existing policy on whether the IDAT chunk needs to be hashed with the pixels and EXIF metadata and adjusting the prototype accordingly.
- Implementing duplicate-chunk detection and mitigation.