Just earlier this year, a finance worker in Hong Kong transferred $25 million to scammers who used deepfake technology to impersonate his colleagues on a video call. Meanwhile AI-generated images of the Pope in a puffer jacket fooled millions online. We’re rapidly approaching a world where distinguishing reality from AI-generated content becomes impossible. So how do we combat it?
There’s not really a good way to verify image authenticity in a scalable or user-friendly way. Leica builds cameras that can sign images but they are upwards of $9k and whenever you make any transformations (e.g. crop, brightness), it invalidates the signature. Adobe has a verifiable content editing pipeline but you have to manually re-apply the edits to verify the output.
At TreeHacks, Sofiane and I built “ProofPix”: an iPhone attested images app and ZK image manipulation library that ended up winning Best ZK Hack and Most Creative On-Chain Hack.
When you download the app, we generate a private/public key pair using the iPhone’s secure enclave (via Apple’s secure storage APIs). This private key signs each photo that’s taken from the app, generating an attestation that the photo was taken from an iPhone camera.
The ZK image editor allows the authenticity of an image to still be verified even through (reasonable) edits. We created a Rust library that performs the image transformations in the SOTA zkVM (Succinct’s SP1) and produces a ZK proof along with the edited image. In order to ensure that someone doesn’t just edit every pixel of the image, we defined a set of reasonable image transformations (e.g. rotate, brighten, crop) that image-editor library supports. We also verify the image’s ECDSA signature in the circuit before applying transformations.
*Fun Fact: We were the first project to use SP1, which had been released just that week!
When an image is uploaded to the internet, it includes metadata that contains the image signature. To ensure that both the iphone that took the image is verifiable (to ensure that a camera took the image, not AI-generated) and that the ZK proof outputted by the image transformations is verifiable, we store a merkle tree of registered iphone public keys and the ZK proofs on-chain.
Challenges
Building ProofPix in 36 hours was relatively challenging due to (1) Apple’s hardware limitations, (2) Rust learning curve, and (3) the new-ness of SP1.
(1) The only way to truly securely authenticate a public key from an iPhone would be for Apple to store a private key in the hardware’s secure enclave and publish a Merkle root of iPhone public keys to a public database. However, Apple doesn’t provide this. We worked around this by using Apple’s secure storage API to generate a private signing key and uploading the public key to the blockchain, though this still left potential attack vectors.
(2) Building the ZK image verification and transformation library required diving deep into Rust during the hackathon, and this was our first time developing something more substantial in Rust beyond “Hello World” programs.
(3) Since SP1 was released literally the week of TreeHacks, we encountered compatibility issues that no one had faced before. For example, the image-rs
crate we used for image processing relied on functions like round
and roundf
that weren’t yet supported in the zkVM. We had to implement these functions ourselves and patch the compiler to use our local implementations. Fortunately, the ZK community’s open-source culture meant we could contribute PRs back to the SP1 repo to help future developers.
Ultimately we overcame these challenges and ended up with a pretty cool project!
**
BUT our mobile app had a major security flaw: How does our server know that the data came from an untampered app instance and a genuine iPhone?
Some malicious actor could reverse-engineer the app and send fake photos to our server, and the server would have no way of knowing the app was tampered with. To fix this, we needed client authenticity proofs.
Sofiane and I joined the Signature Singularity Residency, a one-month residency in Osaka, Japan to explore this direction further.
The solution was App Attest — a protocol built by Apple that enables services to verify that requests came from a real Apple device running the unmodified developer-approved binary. It’s like a tamper seal that proves the data came from an unmodified, genuine iPhone app. Read the docs to learn more.
We ended up building a toolkit for client authenticity with server-side App Attest verification in Rust (along with some other utils like certificate chain verification) and Postcard, a secure attested images app as an example of what App Attest can enable. We also experimented with on-chain App Attest using SP1 for sybil resistance (anti-bot security for mobile flows).
Postcard is a simple image sharing app that consists of a signed photo and some metadata (like location). The signature, along with the App Attest certificate chain, is proof that the photo + location was taken with a genuine Apple device running an untampered app:
This toolkit enables use cases like:
This project is a call to action for companies like Apple to build signature capabilities directly into camera hardware. We envision a future where cryptographic proof, not institutional trust, verifies digital content authenticity. As AI-generated content becomes indistinguishable from reality, cryptographic verification may be our only defense against a post-truth digital world.
**
Links: Twitter thread Pt. 1, Pt. 2. ProofPix, ZK Image Editor, On-chain App Attest. Devpost.