Sigil: Address Verification with Passport - good or bad idea?

TL; DR - I created Sigil which generates a unique nullifier per passport that can be associated with ethereum addresses. This basically enables proof of personhood at the address level and promotes sybil-resistance, i.e. protocols can enforce one passport per protocol rather than per address.

Overview

I started my web3 journey relatively recently and became interested in privacy/identity/ZK proofs specifically. That led to creating an app to prove personhood at the ethereum address level. I wasn’t sure if it was a good or practical idea, but I wanted to just build something so went ahead with it. So how it works – a user first connects to their wallet and then taps a valid passport using their phone, which generates a ZK proof locally. The proof checks the authenticity of the contents and that it was signed by a real CSCA (country issued key). There’s a master list of keys compiled by the ICAO, so I created a separate merkle tree with each hashed key as a leaf. Part of the proof is making sure the CSCA key exists in this list.

The proof generated is then submitted to an on-chain verifier, and if it succeeds, the passport nullifier (unique one-way hash) is stored on a registry along with the transacting address. I also implemented some mechanisms around expiration, unregistering, and registration limits, but the basic idea is that there’s some level of personhood behind the address now.

Sybil Resistance

Another benefit of having passport backed addresses is sybil-resistance. The passport nullifier is unique per passport, so additional addresses that get verified are linked to the same one. So if a protocol leveraging Sigil enforces unique passport nullifiers, a user won’t be able to interact multiple times with different addresses. An example would be something like airdrops.

Similar Projects

There are other passport based projects out there like self.xyz and zkpassport, but these are set up more like per-session proofs, where protocols implement sdks and users have to generate a proof each time they interact. But with Sigil, the proof happens once per address and gets written to a global registry, so any protocol can just read it after that.

Limitations

When I began the project, the idea seemed straightforward, but there were a lot more things to consider around tooling, security, design, and privacy than I initially thought. But that’s usually the case for most of my projects honestly haha. So here are a couple limitations/concerns around how Sigil works at the moment. In particular, I mulled over the privacy concern for a while, so it would be great to get some opinions/thoughts/comments on it.

1) Multiple Passports

If somebody has multiple valid passports, they can verify/register addresses with each of them, and thus be able to interact with protocols multiple times even if unique passports are enforced. So Sigil is unique at the document level and not necessarily individual level. But even at the document level, I think it still greatly helps with sybil resistance.

2) Linked Addresses - Privacy Concern

This is what I mulled over for some time. I was drawn to the idea of having sybil-resistance on web3, so I thought a unique passport nullifier on-chain was a valid approach. However, this does come with a privacy trade-off.

If a user verifies multiple addresses with the same passport, it effectively links them together. This means people will know that certain addresses are most likely owned by the same person.

This really bothered me, and it seemed like the only way to avoid it would be to do per-session proofs per-protocol similar to self.xyz or zkpassport. I also thought about only allowing one address per passport at a time, and generating different nullifiers for subsequent addresses using an incrementing nonce. However, these addresses still become linkable if someone looked at transactions hard enough. So as annoyed as I was, I went with the simpler global nullifier instead and accepted the linkability concern for now. I felt like as long as the user is aware of the risks around accounts being linked to each other, this was an acceptable trade-off. But that’s just me, and I don’t know if there’s something I’m missing or other bigger concerns.

Anyway, would appreciate any feedback or comments on this! It’s been a fun project for me to work on and learn, and if it’s something that gets used, that’s even better. here’s the one page site i set up and the code if anyone wants to look.

www.zksigil.xyz

I’m currently trying to get it published on the App Store (iOS), but I’ve run into a wall where they want me to publish as an organization. So I might try to publish it on Android first.