Inspiration
In early 2024, an employee at a multinational firm in Hong Kong joined a video call with their CFO and several colleagues and wired out 25 million dollars. Every other person on that call was a deepfake. That story stuck with us. AI deepfakes are making it harder every month to know who you're actually talking to, and "I recognize their face and voice" is no longer proof of anything.
At the same time, the internet is filling up with age restrictions. A recent ruling said Meta must limit Instagram Reels for users under 16. Sites have stopped operating in places like Georgia and the UK rather than deal with age verification laws. Discord started requiring full government IDs to prove users were old enough, and those IDs were later exposed in a breach.
We're worried that age checks are becoming an excuse to kill privacy and anonymity online. Kagi is our attempt to take that excuse away. It lets you prove you're over 18 without showing anyone your ID.
The third problem is bots. Twitter and Threads are both full of them (Twitter much worse, but both are rampant). A platform can't fix that without knowing that each account belongs to a unique real person, and today that means handing over your identity.
So we asked:
Can one physical key prove who you are, how old you are, and that you're a unique human, while revealing nothing else?
What it does
Kagi is a physical key issued by a trusted authority. It is cryptographically bound to facts about you (name, date of birth, SSN), but it never stores those facts. It only answers yes or no to specific questions:
- "Is this really Nathan Donagi?" A video call host sends a code, the other person taps their key, and the host sees Verified or Not verified. A deepfake has no key.
- "Are you over 18?" A site like our demo Blindgram learns only "yes". It gets no name, no birthday and no ID photo to leak.
- "Is this a new person?" At sign-up, the site learns only whether this person already has an account. It never learns who they are, so one person gets one account, and bot farms can't sign up thousands of them.
How we built it
Commitments, not facts
The key never holds your data. For each field, the authority stores a salted, slow hash of it (a commitment):
$$ C = \mathrm{PBKDF2}\left( \mathrm{SHA256}(\text{fields}), \ \text{salt} \right) $$
To answer a question, the key hashes the guess the same way and checks whether it matches. Fields are chained together (the SSN commitment also covers the name, date of birth and PIN), so the high-value facts can't be guessed on their own.
Age checks
Age works exactly like every other field. Every supported query ("over 18", "over 21") is stored, and its one-bit answer is hashed just like the name:
$$ C = \mathrm{PBKDF2}\left( \mathrm{SHA256}(\text{query}, \ \text{answer}), \ \text{salt} \right) $$
The key can confirm the answer to a question, but reading its memory tells you nothing about what the answers are.
Proofs that can't be replayed
When the key answers yes, it signs the verifier's fresh random nonce with a secret unique to that device:
$$ \text{proof} = \mathrm{HMAC}\left( \text{device secret}, \ \text{key id} + \text{query} + \text{nonce} \right) $$
A recorded answer is useless for the next check, because the next check uses a different nonce.
Why a stolen key is still safe
The key limits wrong guesses and counts them in EEPROM, so unplugging it doesn't reset the counter. That helps, but it is not what actually protects you.
The real protection is that only the server can generate a query for truly critical information like your SSN, and the server imposes hard rate limits on those queries. Even someone holding your stolen key can't ask it about your SSN on their own, so they can't brute-force it.
One account per person
For sign-ups, our central server stores only an opaque mark for each site:
$$ \text{mark} = \mathrm{scrypt}\left( \mathrm{HMAC}(\text{pepper}, \ \text{site} + \text{person}) \right) $$
It deletes each sign-up session as soon as the website collects its result, so the website learns only "new" or "existing".
The rest of the system
On top of the key, we built:
- a central sign-up server
- demo websites, including Blindgram
- a video-call challenge site
- a desktop app
- an Android app that talks to the PC over Bluetooth
Building with AI
We built all of this by collaborating closely with AI. Several different agents played critical roles, but Claude played an especially critical one. It one-shot many of our demo features and let us build far more than we ever thought we could in a weekend. It even did a large part of our video editing. Watching Claude operate a mobile device to test a UI it had designed was jaw-dropping.
Challenges we ran into
Our biggest challenge was building a physical key that any phone can recognize. We quickly realized RFID/NFC was the only practical option, but we couldn't get it to work with a microcontroller in the time we had. In the end, we split our prototype into two parts:
- An Arduino Nano running a faithful recreation of all the hashing, commitment and HMAC logic in about 2 KB of RAM. This shows the security guarantees are achievable on cheap hardware.
- A user demo with fixed NFC tags. It lacks some of those security guarantees, but it's much closer to what a user of the final product would experience: tap your key on your phone, done.
Fitting the cryptography onto the Nano was a challenge of its own. Our desktop prototype uses scrypt, which needs 64 MiB of memory, and the Nano has 2 KiB. We switched to PBKDF2 with fewer iterations. That trade-off is acceptable because critical queries can only come from the rate-limited server.
What we learned
- Privacy and verification aren't opposites. A yes/no answer is almost always all a verifier actually needs.
- Hardware limits aren't the end of security. Where the key alone can't be strong enough, the system around it (server-only queries and rate limits) can be.
- The gap between "cryptographically sound" and "works when you tap it on a phone" is where most of the engineering lives.
- Working with AI agents changes what a small team can attempt in 36 hours.
What's next
- Getting the full cryptography onto a secure NFC chip, so the key a user taps is the same key that holds the guarantees.
- Replacing the central server's linkable sign-up flow with our blind-signature protocol, so not even the server can connect accounts to people.
Built With
- android-studio
- arduino
- claude
- codex
- cursor
- python
Log in or sign up for Devpost to join the conversation.