An implementation of the NZ COVID Pass spec in Solidity.
- Verifies NZCP pass and returns the credential subject (
givenName,familyName,dob) - Reverts transaction if pass is invalid.
- To save gas, the full pass URI is not passed into the contract, but merely the
ToBeSignedvalue.ToBeSignedvalue is enough to cryptographically prove that the pass is valid.- The definition of
ToBeSignedcan be found here: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
- The NZ Ministry of Health is never going to sign any malformed CBOR
- This assumption relies on the internal implementation of https://mycovidrecord.nz
- The NZ Ministry of Health is never going to sign any pass that is not active
- This assumption relies on the internal implementation of https://mycovidrecord.nz
- The NZ Ministry of Health is never going to change the private-public key pair used to sign the pass
- This assumption relies on trusting the NZ Ministry of Health not to leak their private key
When you call NZCP.readCredSubjExample/NZCP.readCredSubjLive function as part of a transaction, your pass gets stored on blockchain as calldata. This allows 3rd parties to read your COVID pass and reconstruct your NZCP QR code, effectively making your pass public. This is bad since your pass could be then used by anyone. Never verify live passes as part of a transaction on a deployed version of this contract.
Contrary to using NZCP.readCredSubjExample/NZCP.readCredSubjLive function as part of a transaction, using it as merely a view function (e.g. when calling it via "Read Contract" feature on Etherscan) is fine since execution of a view function happens off-chain.
Please note that the limitations above make any practical use of this contract on live passes to be dangerous.
- Prepare
ToBeSignedvalue and thersarray by callinggetToBeSignedAndRsfromjslib/nzcp.json your pass URI - Call either
nzcp.readCredSubjExample(ToBeSigned, rs)ornzcp.readCredSubjLive(ToBeSigned, rs)to verify your pass and get the credential subject
- Run
maketo build the project - You can build without the live pass verification or without the example pass verification by supplying
DFLAGSenvironment variable into themakecommand.make DFLAGS=-DEXPORT_EXAMPLE_FUNCSto build only example pass verificationmake DFLAGS=-DEXPORT_LIVE_FUNCSto build only live pass verification
- Create
.envfile in the root directory of the project - Populate it with at least 1 live pass URI.
- Use
.env.exampleas a reference.
- Use
- Run
make test
- Populate
.envwithALCHEMY_API_KEYandROPSTEN_PRIVATE_KEY - Run
make deploy DFLAGS=-DEXPORT_EXAMPLE_FUNCS NETWORK=hardhatto test deploying - Run
make deploy DFLAGS=-DEXPORT_EXAMPLE_FUNCS NETWORK=ropstento deploy on Ropsten testnet- WARNING: Please don't deploy live pass verification to any remote network, as because executing the verify function as part of a transaction will result in the pass getting stored as calldata on the blockchain and effectively being public.
Running tests consumes 1429033 gas units (optimizer enabled, 1000 runs)
Ropsten testnet: https://ropsten.etherscan.io/address/0x14ffb19a685bb8ec4b925604280f7e441a343af9 (example passes only)
- Test
readCredSubjExamplewith the arguments:ToBeSigned:0x846A5369676E6174757265314AA204456B65792D3101264059011FA501781E6469643A7765623A6E7A63702E636F76696431392E6865616C74682E6E7A051A61819A0A041A7450400A627663A46840636F6E7465787482782668747470733A2F2F7777772E77332E6F72672F323031382F63726564656E7469616C732F7631782A68747470733A2F2F6E7A63702E636F76696431392E6865616C74682E6E7A2F636F6E74657874732F76316776657273696F6E65312E302E306474797065827456657269666961626C6543726564656E7469616C6F5075626C6963436F766964506173737163726564656E7469616C5375626A656374A369676976656E4E616D65644A61636B6A66616D696C794E616D656753706172726F7763646F626A313936302D30342D3136075060A4F54D4E304332BE33AD78B1EAFA4Brs:[0xD2E07B1DD7263D833166BDBB4F1A093837A905D7ECA2EE836B6B2ADA23C23154,0xFBA88A529F675D6686EE632B09EC581AB08F72B458904BB3396D10FA66D11477]
- Test
verifySignExamplewith the arguments:messageHash:0x271CE33D671A2D3B816D788135F4343E14BC66802F8CD841FAAC939E8C11F3EErs:[0xD2E07B1DD7263D833166BDBB4F1A093837A905D7ECA2EE836B6B2ADA23C23154,0xFBA88A529F675D6686EE632B09EC581AB08F72B458904BB3396D10FA66D11477]
N/A