Inspiration
Everyone worries that AI makes fake photos believable. We realized the deeper damage runs the other way: real photos are becoming deniable. "That's AI" now works as a universal dismissal for genuine evidence, whether it's an insurance photo, a news image, or accountability footage. Researchers call this the liar's dividend. AI detectors can't fix it because detection is a losing arms race; every improvement in generators erodes the detectors. So we stopped trying to prove what's fake and built a way to prove what's real.
What it does
Provenance is a camera app that cryptographically attests photos at the moment of capture and anchors the proof on Solana. When you take a photo, the app hashes the image, signs a manifest (hash, timestamp, device key) with an Ed25519 key that never leaves the device's secure store, and writes the attestation to an on-chain registry in seconds. Anyone, forever, can drop that photo into our verifier and get a verdict: green if the exact bytes match an on-chain attestation, amber if it's a recompressed or resized derivative of one (matched by perceptual hash, confirmed against the chain), grey if no record exists. Change a single pixel and verification fails. We don't claim to detect AI. We prove this exact image existed, unmodified, at this moment, from this device, and no one, including us, can forge, backdate, or delete that record.
How we built it
The architecture rests on a deliberate division of labor between our two core technologies: Solana is the trust layer, MongoDB is the intelligence layer. Raw truth (hashes, timestamps, device keys) lives on-chain where nobody can forge, backdate, or delete it. Everything searchable, matchable, and fast lives in MongoDB Atlas, and the entire database can be rebuilt from scratch by replaying the chain.
The Solana side: An Anchor program (Rust) on devnet stores one PDA per photo, seeded by the image's SHA-256, which turns the blockchain itself into a content-addressed lookup table. Verifying a photo requires no search at all: hash the bytes, derive the address, read the account. One RPC call. Anchor's init constraint gives us duplicate rejection for free, so nobody can re-attest someone else's photo after the fact. Solana specifically makes this design economically sane: ~400ms finality and sub-cent fees mean we notarize every photo at the instant of capture, with no batching window during which an edit could slip in. Our Node backend sponsors transaction fees, so users never hold SOL. The capture app signs manifests with an Ed25519 device key from secure storage, and since Solana natively speaks Ed25519, the phone's identity key is literally a Solana keypair.
The MongoDB side: Exact hashes prove exact bytes, but the real world recompresses. Post a photo to a social platform and every byte changes while the image stays "the same." This is where MongoDB earns its place. Alongside each on-chain record we index a 64-bit perceptual hash (pHash), a fingerprint of the image's visual structure that survives recompression and resizing. When a submitted photo has no exact match, we query Atlas for candidate pHashes and rank them by Hamming distance, the count of differing bits, using a conservative threshold we calibrated by round-tripping real photos through Instagram's compression pipeline and measuring the drift. A near-zero distance means "this is a derivative of an attested original," powering our amber verdict tier that pure on-chain lookup could never provide. For the exploratory tier below that, we use Atlas Vector Search over CLIP embeddings to surface visually similar attested captures as leads, and deliberately never as verdicts, because semantic similarity is the wrong question for verification. MongoDB's flexible document model let both matching strategies live beside the chain metadata in one collection.
The rule joining them: Mongo proposes, the chain disposes. Every candidate the database surfaces is confirmed by a direct on-chain read before anything is displayed. Our litmus test: could the verifier lie if the database lied? No. A fabricated Mongo record fails chain confirmation and shows nothing, while a hidden record degrades a verdict to "no match," never the reverse. A reindex script that rebuilds Atlas entirely from on-chain accounts makes the trust story literal: MongoDB makes the system fast and smart, and Solana makes it honest.
The app: One Expo (React Native/TypeScript) codebase serves both capture (native, with the secure-store signing key) and verification (exported to web on Vercel, so anyone can verify from a browser with nothing installed).
Challenges we ran into
The public devnet RPC rate-limited our program deployment into a 3-minute crawl of retries, which taught us early to get a dedicated RPC endpoint before the demo rather than during it. We hit a race condition where transactions confirmed on chain but reads landed before propagation, a small but real lesson in the difference between "sent" and "readable" on a distributed system. Expo Go's supported SDK version didn't match our scaffold, forcing a three-version downgrade and an API cleanup pass.
Accomplishments that we're proud of
A live end-to-end loop: photograph anything, and the attestation is on the public Solana explorer seconds later, verifiable by anyone from their own phone. The tamper demo, where editing one pixel flips a verdict from green to grey, makes the cryptography visceral in under thirty seconds. We're proud that the amber tier survives a real platform round trip, catching recompressed derivatives that exact hashing would miss, and equally proud of what we refused to build: no "AI detector" theater, no verdicts our chain can't back. The registry can be fully rebuilt by replaying on-chain accounts, which makes our "you don't have to trust us" pitch literally true rather than rhetorical.
What we learned
Solana development end to end: Anchor programs, PDAs as content-addressed storage, transaction confirmation semantics, and why sub-cent fees and fast finality are what make per-photo notarization economically sane. We learned that C2PA, the industry's provenance standard, fails at the last mile because platforms strip embedded metadata on upload, and that an external registry is the fix its own roadmap points toward. We learned perceptual hashing, and where its rigidity is a feature. Most of all we learned that in a trust product, the pitch discipline is the product: every claim you don't overmake is a failure mode you don't have.
What's next for Provenance
Hardware attestation is the big one: App Attest and Play Integrity slot into an existing manifest field, upgrading device-bound keys to hardware-backed proof once we ship store builds. Edit lineage lets legitimate crops and adjustments carry a chain of custody back to a verified original. A Merkle-root-per-device design keeps on-chain storage constant regardless of photo volume. Longer term: video via frame-fingerprint sequences, identity linking so a photojournalist can prove a post is their capture, and pilots with the users who need this today, including insurance adjusters, journalists already being falsely AI-flagged, and landlords documenting move-ins. The end state we're betting on is capture-time provenance built into every camera. We built the missing piece: an anchor that can't be stripped.
Built With
- anchor
- expo.io
- mongodb
- node.js
- react-native
- rust
- solana
- typescript
Log in or sign up for Devpost to join the conversation.