Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC-0007: zkPassport #11

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions RFCs/rfc-0007-zkPassport.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# RFC-0007: zkPassport

- **Intent**: Create a private identity primitive for Mina and connected ecosystems that is secure and accessible.
- **Submitted by**: Evan Shapiro (Github: @es92, Twitter: @evanashapiro)
- **Submitted on**: January 8th, 2024

## Abstract

This RFC proposes a grant to build a private proof-of-passport attestation (zkPassport) leveraging smartphone NFC, ZKPs, and Mina, with an aim to provide a private identity primitive for Mina, blockchains that are connected to it, and ultimately web2 applications.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! 🦾


## Introduction

A secure, widely accessible implementation of private identity (proof-of-personhood) would be very useful for the blockchain ecosystem and for digital systems broadly.

This could be leveraged by applications on Mina, applications on any bridged chains (eg Ethereum), or any web3-connected web2 applications.

Use cases include:
* Proving proof of uniqueness, to apply to use cases such as one person one vote, one person one account, one person one airdrop, etc.
* Proving facts about identity (nationality, age, etc).

Historically, this has been challenging to bootstrap and make accessible without some prior information to "anchor" digital identity to.

One widely accessible place that identity information has been stored, including with cryptographic signatures and roots of trust, is passports. It seems that for decades now, passports have come with (1) NFC, (2) digital representations of their data, and (3) cryptographic signatures by their host countries[[1](https://www.icao.int/Security/FAL/PKD/Pages/ePassport-Basics.aspx),[2](https://en.wikipedia.org/wiki/Biometric_passport)]. As of writing, it seems there are currently over 140 countries issuing biometric passports.

Using this information directly online would expose passport information online, which would not be viable.

However, with ZKPs, users could provide proofs about their passport information, without exposing the passport information itself.

Additionally, because passports following this standard support NFC, which is present on most smartphones, users can obtain this data themselves from their own passports relatively easily. Here for example is an open library that reads passports for iOS[[3](https://github.com/AndyQ/NFCPassportReader)].

Properties stored in the standard include:
* documentType
* documentSubType
* documentNumber
* issuingAuthority
* documentExpiryDate
* dateOfBirth
* gender
* nationality
* lastName
* firstName
* names
* placeOfBirth
* residenceAddress
* phoneNumber

## Objectives

We propose a grant taking advantage of this, implementing, at a high level, the following:

1. An iOS & Android App that uses NFC to allow users to get the data from their own passports, and store that data in their MINA wallet for secure use by web3 applications through the (in-progress) Mina Attestation API Standard.
2. An o1js library that uses the Mina Attestation API Standard to create proofs of various components of one's zkPassport identity, for use in proof-of-unique-user and proof of nationality & age use cases.
Comment on lines +51 to +52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another great feature would be if the zkPassport is a credential owned by the user & stored in the wallet, then compliance with W3C Verifiable Credentials Data Model. This would help applications that held the credential to standardise indexing and handling of the credential.

I'll also post the wallet attestation APIs shortly that can be referenced here too.

Copy link

@Pfed-prog Pfed-prog Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very curious if there is a need for a iOS & Android App when NFC could be connected with a standard browser similar to friend.tech

Tested the following website with my cheapish Android phone on Chrome

https://whatwebcando.today/nfc.html

Some Dell computers also come with NFC

https://www.dell.com/support/kbdoc/en-in/000129573/how-do-i-use-near-field-communication-nfc-on-dell-systems

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using NFC scanning directly in the browser instead of creating separate iOS & Android app would make the process more modular and user-friendly, I think. It would be simpler and more direct: go to a website, scan your passport using NFC, and then transfer the data to your wallet, zkApp, etc.

I think the Web NFC API currently only supports basic scanning functions. With a passport NFC scan, there's an additional step to decrypt the data using a key found on the passport's first page. This particular interaction isn't included in the native Web NFC API, I think.

I hope this is achievable. Such a fantastic use case.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the Web NFC API doesn't support reading passport unfortunately.


## Motivation and Rationale

This would unlock many use cases for web3 and web2 applications connected to Mina.

For applications on Mina, they can directly take advantage of this data through nullifiers for proof-of-uniqueness and other identity related proofs (see both scenarios below).

For other chains, using Mina's zk state bridge, they could also leverage these proofs in their applications.

Web2 applications may find use in this functionality as well. This seems particularly relevant as AI systems become increasingly powerful, and the risk this could pose to new and existing digital systems being overwhelmed by fake users.

## Scenarios and Use Cases

### Example Scenario 1: Proof-of-Uniqueness

| Aspect | Description |
|------------------|-------------|
| **Description** | A zkApp wants a user to prove they are unique. |
| **Requirements** | An implementation of zkPassport in the Attestation API Standard (see objectives), plus an on-chain nullifier that users can use with the zkApp. zkPassport nullifier proofs should be sure to have a *context* input salt that is hashed with the unique zkPassport identifier to ensure identities are unique across their context, but cannot be associated cross-context unless a proof is provided by the user. |
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KimlikDAO-bot this is one way to ensure that identities aren't traceable cross application - the salt can make sure that how one proves uniqueness for one application isn't traceable across applications.

It would probably be important that however wallets interact with nullifiers, wallets check and make sure the same nullifier-key isn't being used across applications

Copy link

@KimlikDAO-bot KimlikDAO-bot Feb 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlinkability between different on-chain uses can be achieved via nullifiers, we are in agreement there. This is also how our HumanIDv2 is designed.

The devil lies elsewhere: ensuring unlinkability between any of the on-chain uses and my IRL id. It appears that there is no way to achieve this if the user generates the proof-of-uniqueness secret in isolation (without talking to anyone else)

Any time you use the outlined system, anyone observing the Mina blockchain can just brute force the user passport number or SSN, whatever constant value we're using for the secret generation.

For instance folks below are suggesting using (name, lastName, localIdNumber) as the basis for proof-of-uniqueness secret. With this proposal, taken on face value, anytime a user includes a nullifier in a Mina tx, we can easily brute for the (name, lastName, localIdNumber) of the user

The path from (name, lastName, localIdNumber) to the nullifier is entirely deterministic. (It has to be, otherwise it will not ensure uniqueness)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's a good point. I think for this passport case, I think there should be enough data to avoid this, by using the passport signature from the authority itself as part of the hash - so unique_passport_hash = hash(passportSignature, passportData), and it shouldn't be brute-forceable I think.

And then using hash(application_salt, unique_passport_hash) for any nullifiers on-chain to avoid revealing the unique_passport_hash, seems like it should work. Even if the application_salt is constant, there shouldn't be a way to find the unique_passport_hash then, (or the additional requirement of creating a proof that one possesses the data underlying that hash that has been signed by the passport authority).

Any group implementing / auditors should definitely make sure this works out in the implementation and specifics of any passport cryptography though, as well as put together a more complete spec. Curious if you think this seems right or any other thoughts though.

Copy link

@KimlikDAO-bot KimlikDAO-bot Feb 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of using the passport signature as entropy. This gives the passport signing authority (or even airlines) full surveillance over all on-chain sybil detection. Anytime someone uses on-chain sybil detection, the full passport data becomes available and gets linked to their wallet address for certain organizations and companies.

The good news is that we have found a solution through a novel zk protocol: the user has to talk with n parties but in a totally zero-knowledge way. While minting their on-chain ID, the user engages in bilateral communication with n parties (nodes) to obtain their secret shares and combine them in their own device. This bilateral communication reveals nothing about the user, based on the security assumptions of Kimchi. At the end, the user obtains a proof-of-uniqueness secret which provides

  • information theoretic unlinkability to their IRL ID, even from the perspective of n-1 colluding nodes.

  • different on-chain uses (through nullifiers) are unlinkable based on Kimchi assumptions (just like in this proposal)

Full details: https://zkignite.minaprotocol.com/zkignite/zkapp-cohort-3/feedbackandrefinement/suggestion/739/detail

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, yeah that makes a lot of sense. Yeah it would probably be best to avoid the passport authority being able to do that.

Maybe the following could be done to do this without needing a multiparty protocol? (and any additional trust assumptions that would need to follow from that?)

  1. have an "identity-registration" zkApp, that uses a nullifier using the passport-authority-visible hash as the key, to allow users to register their own user-selected unique hash.
  2. have other applications use the user-selected hash for proofs of uniqueness - which should work because each user-selected hash corresponds to an passport-authority-generated hash, and there isn't a way to generate multiple user-selected hashes per passport-authority generated credential.

Curious on any thoughts? Seems like something multistage is needed though yeah for on-chain privacy from the passport authority.

Copy link

@KimlikDAO-bot KimlikDAO-bot Feb 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the Bloom filter: not only do we get the final Bloom filter, but also all the intermediary steps. This should reveal the same as the Merkle tree, no? There may be a solution along these lines though

Differential privacy literature may have something for this

There may be a randomized algorithm for this and the user may prove that I know a seed such that Poseidon(seed) is used as the random source for the algorithm and ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well actually I think the front-running thing can be solved with a commit-and-reveal scheme. You "preregister" first, by showing a blinding commitment to P i.e. H(S, P). And it's only possible to register once n blocks have passed since a preregister was done. So, unless someone manages to completely block you from posting a transaction for n blocks, they aren't able to front-run it because they'd need to create their own preregistration after seeing your data

Yep - further, the zkApp can require a proof that alice knows S in H(S), so knowing H(S) shouldn't be enough to front-run then either (if we're talking about front-running H(S)).

I'm not sure on the entropy, but I'll add that to a "todo" section of this RFC - I'd think there'd be enough entropy between all the data in P (includes I think maybe fingerprint / photo data as well?) and the signature from the issuing authority, but its definitely something someone on the cryptography side should check (it sounds like definitely a risk at least to make sure of).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on passport since they are all around the place but majority of them have very low entropy because of limited bit space they have and data they need to put in to that space.

Copy link

@KimlikDAO-bot KimlikDAO-bot Feb 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on passport since they are all around the place but majority of them have very low entropy because of limited bit space they have and data they need to put in to that space.

This is false. Even if you put 128bit RSA signatures behind a hash function they will have roughly 128 bits of entropy. I cannot fathom passports having less than 128 bit RSA. Note RSA 128 is believed to have less than 30 bits of security if you show the signature outright (without hashing)

Copy link

@EmrePiconbello EmrePiconbello Feb 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://eprint.iacr.org/2005/095.pdf

This is the most detailed document. While this is old if you do your research you can find this still applies to many passports globally. The biggest problem comes from general practices since this paper didn't change. Few countries changed their structure and it's safer, majority of them didn't make that. There is a new standard published but it's a big question when it's adopted or even at all.

| **Expected Outcome** | Via leveraging a simple library, users can make zkApps that are sybil-resistant. |
| **Impact Analysis** | This would unlock many applications, such as one-person-one-vote, one-person-one account, Sybil-Resistant airdrops, etc. |

### Example Scenario 2: Proof-of-nationality

| Aspect | Description |
|------------------|-------------|
| **Description** | A zkApp wants a user to prove facts about what country they are / are not from. |
| **Requirements** | An implementation of zkPassport in the Attestation API Standard (see objectives). |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another requirement would be to use the Attestation API to recursively prove many properties of a credential. For example Prove(Prove(nationality===UK) & Prove(documentExpiryDate>currentBlockHeight)).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will be good to add a link to the mentioned MINA Attestation API.

| **Expected Outcome** | Via leveraging a simple library, zkApps can require a user to prove facts about their nationality. |
| **Impact Analysis** | This would be useful across web3, to make applications that are regulatory-compliant. |

## Implementation with Wallet Attestation API

zkPassword would be integrated via (and ideally developed in tandem with) the Wallet Attestation API. It would use the to-be-defined in detail "FlatCredential" program. The credential uploaded to the Attestation API, following the FlatCredentialAttestation spec, would look as follows:

```
{
documentExpiryDate: (Jan 01 2028: Date),
dateOfBirth: (Jan 01 2000: Date),
nationality: ("USA": String),
firstName: ("Alice": String),
...
credentialHash: ("xb82818...": SHA256Hash),
credentialHashSignature: ("ntn838...": PassportSignature),
}
```

And the attestation spec would be called with an object created in the browser as follows. The wallet would use this object to compute the attestation.

```
let verifier = new FlatCredentialVerifier();
const hash = verifier.sha256Hash([ verifier.field('nationality'), ... ]);
verifier = verifier.checkEqual('credentialHash', hash);
verifier = verifier.verifySignature('credentialHashSignature', verifier.field('credentialHash'), countryPublicKey);

verifier = verifier.checkEqual('nationality', 'USA')

const zkProof = AttestationAPI.createAttestation(verifier);
}
```

The AttestationAPI would let the user know what fields of the credential are being requested and what the verifier is asking to know about those fields. More details should be included in the AttestationAPI documentation for the proposed FlatCredential program.

It will be up to the implementer of this RFC to work with the implementer of the Attestation API RFC to ensure the relevant cryptography and methods are included in FlatCredentialv0 to cover zkPassport.

It is expected multiple versions of FlatCredential will be built with additional cryptography supported, to support more and more attestation sources.

The implementation should also include an identity anonymizing zkApp (see comments on github), to insure the passport issuer cannot see the user's on-chain activity through their knowledge of P and H(P).

## Open Issues and Discussion Points

A remaining question is exactly what new cryptography primitives would need to be implemented in o1js, if any new ones are needed. It looks like RSA, DSA, ECDSA, and Sha-xxx are used (see pages 15, 16, and 17 here[[4](https://www.icao.int/publications/Documents/9303_p12_cons_en.pdf)]).

It seems countries keep databases of lost, stolen, and revoked travel documents[[5](https://www.icao.int/publications/Documents/9303_p2_cons_en.pdf)]. It doesn't seem like this is public however, so there may also have to be logic for invalidating one's old passport if one gets a new passport (due to the old one either being lost, stolen, revoked, or just expired).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They have their own databases but it's not public. When passport is issued. The certification and data of it is valid on average 10years +3 months. So if they are stolen, lost etc. You can't use it to exit the country since they would know while you trying to leave. To my knowledge from NFC stand point there is no difference and I don't know any country with public DB on these documents.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that 10 years is the number due to expiration of NFC tags

Copy link

@Pfed-prog Pfed-prog Feb 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Belgium citizens can log in to their government services portal with eID card reader
https://www.youtube.com/watch?v=RBFe-FdPw34
It only requires a pin number, eID card reader and a card

The security can certainly be enhanced with MFA

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you outlined here is eID not a passport. The 10 years is because passports are mostly valid for 10 years the problem is NFC is permanent the certificate is 10 years + few months so if it's stolen or something it will be always valid when you are checking it according to certificate.

Copy link

@Pfed-prog Pfed-prog Feb 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, NFC tags typically expire in 10 years. I have seen this number on vendors pages, articles, etc

For example,

Finally, NFC tags could also be deleted if their data retention time expires. Data retention on NFC tags is intended to last for a set amount of time, typically 10 years. The tag might not be able to keep data properly if the data retention time has passed.

https://taptag.shop/blogs/how-tos/ways-an-nfc-tag-or-nfc-card-can-be-erased-magnets-heat-etc

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but we can create an api service that helps in emergencies and that stores and is responsible for the data storage

Copy link

@Pfed-prog Pfed-prog Feb 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is NFC Tag Issuance Process from Near Field Communication (NFC) Technology with Jordan Mobile Payment (JoMoPay) https://www.cbj.gov.jo/EchoBusV3.0/SystemAssets/PDFs/EN/NFC.pdf
image

NFC Transaction Flow
image

there are 3 pages more in the pdf

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, any architecture makes it possible to override a previously registered passport with a newer one. That seems to be an important fallback flow in case your identity is stolen. If that is possible, it doesn't matter how long the original passport or NFC tag is valid

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that covers cloning or stolen at all. As random people from earth's population. I will never learn my identity utilized on mina blockchain in the first place.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it doesn't cover that (a liveness test is also needed), but in an ideal system you can still override an old passport + liveness test with a newer one, and so it doesn't matter how long the old one is valid


Lastly, a passport isn't something that everyone has or is able to get, so this is unlikely to work as a universal solution for proving personhood. That said, it could be a useful "anchor", for decentralized social-graph based approaches, which I think could be promising future work.

This could be done via passport-holders verifying non-passport-holders. One way this could work is requiring multiple passport-holders, say 3, to attest to the validity of a non-passport-holder, and limiting the number of times they can do this (if 3 passport-holders are required, and each passport-holder gets 3 verifications, this would mean each passport-holder could verify up to one non-passport-holder on average).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Social identity is really cool, I like this one! 💡

Copy link

@mazito mazito Jan 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting but really difficult to avoid collusion of passport holders to validate a fake/malicious non passport holder. The validated malicious non-holder can latter perform malicious actions without any difficulty. The non-holder may not even exist and be just a way of the 3 holders to act together and perform some action. Having no traceability back from the initial holder approvers to the fake non-holder also makes it quite worse.

Validating identity by social methods is much more complex. ProofOfHumanity has some way of doing it, we used randomly chosen anonymous trusted validators in the Identicon protocol (the idea that originated Socialcap), and there are others.

Copy link

@Pfed-prog Pfed-prog Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BrightID is another viable identity model


Revoking identity and multiple validations could be another way to solve this

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proof of uniqueness can be a solution here if user don't have passport or prefer not to share the data. Any kind of social system is always open to be gamed

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think the solution is to track every single person all the time


Applications using zkPassport should be very clear what exactly it is they are proving - specifically, proof of having had access, at some point during a passports lifetime, to the data contained on the passport's NFC chip.

Users of applications should be careful to keep their passports secure. Note that passport RFIDs can only be read while the passport is open and a portable reader is within 6" of the passport, somewhat mitigating this risk.

However if a user suspects someone may have had access to their passport they should consider expiring it and getting a new one (open question: how hard is this to do?), and an implementation of zkPassport should include logic for expiring old passports and replacing them with new ones.

Additionally, there are various social and privacy risks to enabling digital composable identity. Including a "context"-specific salt in nullifiers is mentioned above as one way to ensure users have choice over what to expose about their cross-context identity-specific operations. But other risks and mitigations should be considered as well with this new technology.

## Conclusion

This RFC proposes an implementation of a private identity system leveraging passports (zkPassport) for use in the Mina Ecosystem and any connected chains.

## TODO

* Check that o1js supports all of the relevant cryptography, or see what would be left to be implemented
* Make sure there is enough entropy in P that H(P) can't be brute-forced

## Appendices



## References

International Standard Docs[[6](https://www.icao.int/publications/pages/publication.aspx?docnum=9303)].

See other links in-line.