Comparing ZK-SNARKs to NFTs for assertion of membership
The way Signata works for the assertion of rights can be summed up as follows:
- An identity A uses the blockchain to assert itself onto an identity register.
- Identity A purchases right X, such as completing KYC through a provider. X is minted by the provider as an NFT bound to a specific schema.
- Identity A's delegate authenticates, showing it is the delegate for A and holds right X.
Any time a service wants to validate that an identity has completed a KYC check, then it simply needs to check if the address is holding one of those NFT rights. If a different address wants to assert the same right, then it just needs to prove that it controls the keys for identity A by cryptographically signing a piece of data for the service checking it.
So if we consider using ZK-SNARKs instead, we can examine Vitalik's example of a proof of membership:
Suppose that you have an Ethereum wallet, and you want to prove that this wallet has a proof-of-humanity registration, without revealing which registered human you are. We can mathematically describe the function as follows:
# The private input (w): your address A, and the private key k to your address
# The public input (x): the set of all addresses with verified proof-of-humanity profiles {H1...Hn}
# The verification function f(x,w):
- Interpret w as the pair (A,k), and x as the list of valid profiles {H1...Hn}
- Verify that A is one of the addresses in {H1...Hn}
- Verify that privtoaddr(k)=A
- Return True if both verifications pass, False if either verification fails
So how would you build this into a service? Well fundamentally you'd need to be using a separate address that is added to a registry of addresses (similar to how Signata works). When asserting that you have the right to access a service, you would be connecting with some address B and providing a ZK proof derived from address A to show that you're in control of it. The provider would see that proof, can validate that it's somewhere in that registry of addresses, and grant access.
This kind of assertion for access control is limited in 2 ways:
- You can't assert something like a KYC proof, as KYC proofs need to have a path of reconstruction back to the original identity. If you're asserting "yes I have an address on the list but you don't know what it is, only that I hold it", then that path to the KYC proof is broken.
- It only provides privacy at scale. If the registry only has a small number of addresses in it then it's effectively useless. You would need well beyond 100 addresses with plenty of on-chain activity to muddy the waters enough to preserve privacy.
And so we see that using ZK-SNARKs for access control is really just too limited. At the very most it can provide a simple assertion of existence in a registry, but it cannot provide sophisticated authorization. We wouldn't recommend trying to use them for asserting proof of KYC, as it's not consumable in the way KYC needs to be consumable.
Complex authorization works the best when asserted as NFTs. To maintain privacy, spread the NFTs to addresses that don't actually interact on-chain. Reveal you hold the keys to that address to those services that you want to, not the entire world. The power of web3 is that you can freely create as many keys as you need, rather than having everything funneling back to a single email address representing your identity.