Skip to main content

ZK Passport smart contracts reference

A set of contracts facilitating self-issued anonymous identities based on the ZK Passport tech.

Currently, there are seven contract sections:

  1. State — main StateKeeper contract and a set of utility contracts. StateKeeper acts as a singleton state instance with which registration contracts interact. StateKeeper does the following:
    • Stores the Sparse Merkle Tree with registered identities;
    • Stores the Sparse Merkle Tree with registered certificates of ICAO members;
    • Stores and manages some passport and identity information;
    • Manages the "Passport <> Identity" bonds.
  2. Registration — primary section with Registration and Registration2 contracts, that:
    • Allow users registration (with binding of their identity to the passport);
    • Allow revocation of passport-identity binding;
    • Allow re-issuance of previously revoked identity;
    • Allow registration and revocation of ICAO member's certificates (calls StateKeeper);
    • Call one of the verifier contracts, based on the provided passport type, to verify ZKP;
    • Manage different dispatchers.
  3. Verifiers — auto-generated contracts, the main purpose of which is to verify the ZKP.
  4. Dispatchers — acts as a bridge between registration contracts and:
    • authenticators corresponding to different passport types, if it is a passport dispatcher;
    • signers, if it is a certificate dispatcher.
  5. Signers — responsible for verifying the signature of the ICAO member's certificate. It also stores information required for signature verification (e.g. RSA exponent).
  6. Authenticators — perform the passport Active Authentication (AA).
  7. Utilities — some utility contracts, such as X509, SHA1, RSA implementations in solidity language and other.

Registration

Interface

contract Registration is Initializable, TSSUpgradeable {

StateKeeper public stateKeeper
mapping(bytes32 => address) public certificateDispatchers;
mapping(bytes32 => address) public passportDispatchers;
mapping(bytes32 => address) public passportVerifiers;

function registerCertificate(
Certificate memory certificate_,
ICAOMember memory icaoMember_,
bytes32[] memory icaoMerkleProof_
) external {
/* ... */
}

function revokeCertificate(bytes32 certificateKey_) external {
stateKeeper.removeCertificate(certificateKey_);
}

function register(
bytes32 certificatesRoot_,
uint256 identityKey_,
uint256 dgCommit_,
Passport memory passport_,
VerifierHelper.ProofPoints memory zkPoints_
) external {
/* ... */
}

function revoke(uint256 identityKey_, Passport memory passport_) external {
/* ... */
}

function reissueIdentity(
bytes32 certificatesRoot_,
uint256 identityKey_,
uint256 dgCommit_,
Passport memory passport_,
VerifierHelper.ProofPoints memory zkPoints_
) external {
/* ... */
}

function updateDependency(
MethodId methodId_,
bytes calldata data_,
bytes calldata proof_
) external {
/* ... */
}
}
  • stateKeeper — instance of StateKeeper contract that saves all data about registrations, certificates, etc;
  • certificateDispatchers — mapping from ICAO member's certificate to its dispatcher;
  • passportDispatchers — mapping from passport type to its dispatcher contract;
  • passportVerifiers — mapping from passport type to its verifier contract;
  • registerCertificate(...) — registers an ICAO member's X509 certificate in the certificates SMT (calls StateKeeper contract);
  • revokeCertificate(...) — revokes an expired ICAO member's X509 certificate (calls StateKeeper contract);
  • register(...) — registers the user (identity) by its passport, technically — issues the identity, calls the dispatcher to verify ZKP, links the identity to its passport by calling StateKeeper;
  • revoke(...) — revokes the identity and its passport by the user's will, marks the passport (and identity) as revoked;
  • reissueIdentity(...) — issues previous passport <> identity bond by migrating to a new identity;
  • updateDependency(...) — adds or removes, depending on the method provided, a dispatcher via Rarimo TSS;

For the full implementation, see Registration.sol at the GitHub.

Registration2

Interface

contract Registration2 is Initializable, TSSUpgradeable {

StateKeeper public stateKeeper;
mapping(bytes32 => address) public certificateDispatchers;
mapping(bytes32 => address) public passportDispatchers;
mapping(bytes32 => address) public passportVerifiers;

function registerCertificate(
Certificate memory certificate_,
ICAOMember memory icaoMember_,
bytes32[] memory icaoMerkleProof_
) external virtual {
/* ... */
}


function revokeCertificate(bytes32 certificateKey_) external virtual {
stateKeeper.removeCertificate(certificateKey_);
}


function register(
bytes32 certificatesRoot_,
uint256 identityKey_,
uint256 dgCommit_,
Passport memory passport_,
VerifierHelper.ProofPoints memory zkPoints_
) external virtual {
/* ... */
}

function revoke(uint256 identityKey_, Passport memory passport_) external virtual {
/* ... */
}

function reissueIdentity(
bytes32 certificatesRoot_,
uint256 identityKey_,
uint256 dgCommit_,
Passport memory passport_,
VerifierHelper.ProofPoints memory zkPoints_
) external virtual {
/* ... */
}

function updateDependency(
MethodId methodId_,
bytes calldata data_,
bytes calldata proof_
) external virtual {
/* ... */
}

}

The main difference between Registration and Registration2 contracts is that they use different ZK registration schemas.

  • stateKeeper — instance of StateKeeper contract that saves all data about registrations, certificates, etcß;
  • certificateDispatchers — mapping from ICAO member's certificate to its dispatcher;
  • passportDispatchers — mapping from passport type to its dispatcher contract;
  • passportVerifiers — mapping from passport type to its verifier contract;
  • registerCertificate(...) — registers an ICAO member's X509 certificate in the certificates SMT (calls StateKeeper contract);
  • revokeCertificate(...) — revokes an expired ICAO member's X509 certificate (calls StateKeeper contract);
  • register(...) — registers the user (identity) by its passport, technically — issues the identity, calls the dispatcher to verify ZKP (that was created using a different schema, compared to Registration), links the identity to its passport by calling StateKeeper;
  • revoke(...) — revokes the identity and its passport by the user's will, marks the passport (and identity) as revoked;
  • reissueIdentity(...) — re-issues previous passport <> identity bond by migration to a new identity;
  • updateDependency(...) — adds or removes, depending on the method provided, a dispatcher via Rarimo TSS;

For the full implementation, see Registration2.sol at the GitHub.

Verifiers

Interface

contract ExampleVerifier {

/* some constants */

function verifyProof(
uint[2] calldata _pA,
uint[2][2] calldata _pB,
uint[2] calldata _pC,
uint[4] calldata _pubSignals
) public view returns (bool) {
/* ... */
}
}

All verifiers are generated contracts that share the same interface. However, each verifier is designed to accept proofs generated by specific ZK schemas. Below is a list of the current verifiers:

  • PUniversal2048Verifier — used to create ZKPs that will be accepted by Registration;
  • PUniversal4096Verifier — used to create ZKPs that will be accepted by Registration;
  • PUniversal2048Verifier2 — used to create ZKPs that will be accepted by Registration2;
  • PUniversal4096Verifier2 — used to create ZKPs that will be accepted by Registration2;
  • PInternalOptVerifier2 — internal verifier for Registration2;
  • PInternalVerifier2 — internal verifier for Registration2;
  • PMNEOptVerifier2 — internal verifier for Registration2;
  • verifyProof(...) — verifies passport validity ZKP;

For the full implementation, see verifiers for Registration and verifiers for Registration2 at the GitHub.

PECDSASHA1Dispatcher

Interface

contract PECDSASHA1Dispatcher is IPassportDispatcher, Initializable {

address public authenticator;

function authenticate(
bytes memory challenge_,
bytes memory passportSignature_,
bytes memory passportPublicKey_
) external view returns (bool) {
/* ... */
}

}
  • authenticator — address of the ECDSASHA1Authenticator contract for passports;
  • authenticate(...) — authenticates the ECDSASHA1 passport;

For the full implementation, see PECDSASHA1Dispatcher.sol at the GitHub.

PNOAADispatcher

Interface

contract PNOAADispatcher is IPassportDispatcher, Initializable {

function authenticate(
bytes memory,
bytes memory passportSignature_,
bytes memory passportPublicKey_
) external pure returns (bool) {
return passportSignature_.length == 0 && passportPublicKey_.length == 0;
}

}

This is a special dispatcher for passports without Active Authentication.

  • authenticate(...) — authenticates the passport without AA. Just return true;

For the full implementation, see PNOAADispatcher.sol at the GitHub.

PRSASHA1Dispatcher

Interface

contract PRSASHA1Dispatcher is IPassportDispatcher, Initializable {

address public authenticator;

function authenticate(
bytes memory challenge_,
bytes memory passportSignature_,
bytes memory passportPublicKey_
) external view returns (bool) {
return
PRSASHA1Authenticator(authenticator).authenticate(
challenge_,
passportSignature_,
passportPublicKey_
);
}

}
  • authenticator — address of the RSASHA1Authenticator contract for passports;
  • authenticate(...) — authenticates the RSASHA1 passport;

For the full implementation, see PRSASHA1Dispatcher.sol at the GitHub.

CRSADispatcher

Interface

contract CRSADispatcher is ICertificateDispatcher, Initializable {

address public signer;

function verifyICAOSignature(
bytes memory x509SignedAttributes_,
bytes memory icaoMemberSignature_,
bytes memory icaoMemberKey_
) external view override returns (bool) {
return
ICertificateRSASigner(signer).verifyICAOSignature(
x509SignedAttributes_,
icaoMemberSignature_,
icaoMemberKey_
);
}

}

As for passports, there are authenticators for certificates, and it's one of them.

  • signer — address of the CRSASigner or CRSAPSSSigner contract for certificates;
  • verifyICAOSignature(...) — verifies RSA signature of ICAO member's certificate;

For the full implementation, see CRSADispatcher.sol at the GitHub.

CRSAPSSSigner

Interface

contract CRSAPSSSigner is ICertificateRSASigner, Initializable {
uint256 public exponent;
bool public isSha2;

function verifyICAOSignature(
bytes memory x509SignedAttributes_,
bytes memory icaoMemberSignature_,
bytes memory icaoMemberKey_
) external view override returns (bool) {
return
RSAPSS.verify(
x509SignedAttributes_,
icaoMemberSignature_,
abi.encodePacked(exponent),
icaoMemberKey_,
isSha2
);
}
  • exponent — RSAPSS exponent;
  • isSha2 — hash function switcher, true - sha2, false - sha512;
  • verifyICAOSignature(...) — verifies ICAO member RSAPSS signature of the X509 certificate SA;

For the full implementation, see CRSAPSSSigner.sol at the GitHub.

CRSASigner

Interface

contract CRSASigner is ICertificateRSASigner, Initializable {
uint256 public exponent; // RSA exponent
bool public isSha1; // hash function switcher, true - sha1, false - sha2

function verifyICAOSignature(
bytes memory x509SignedAttributes_,
bytes memory icaoMemberSignature_,
bytes memory icaoMemberKey_
) external view override returns (bool) {
/* ... */
}
}
  • exponent — RSA exponent;
  • isSha2 — hash function switcher, true - sha2, false - sha512;
  • verifyICAOSignature(...) — verifies ICAO member RSA signature of the X509 certificate SA.;

For the full implementation, see CRSASigner.sol at the GitHub.

PECDSASHA1Authenticator

Interface

contract PECDSASHA1Authenticator {

/* brainpool256r1 parameters */

function authenticate(
bytes memory challenge,
uint256 r,
uint256 s,
uint256 x,
uint256 y
) external pure returns (bool) {
/* ... */
}

}
  • authenticate(...) — checks active authentication of a passport (ECDSA signature);

For the full implementation, see PECDSASHA1Authenticator.sol at the GitHub.

PRSASHA1Authenticator

Interface

contract PRSASHA1Authenticator is Initializable {

uint256 public exponent; // RSA exponent

function authenticate(
bytes memory challenge_,
bytes memory s_,
bytes memory n_
) external view returns (bool) {
/* ... */
}
}
  • exponent — RSA exponent;
  • authenticate(...) — checks active authentication of a passport (RSA signature);

For the full implementation, see PRSASHA1Authenticator.sol at the GitHub.