ZK-ID and Registrars
Last updated
Was this helpful?
Last updated
Was this helpful?
Note: the registrars, as described in the below article are optional in the design of shielder, and as such they are not part of any of the production deployments of Shielder (see , and subsequent).
Each user of the Shielder must generate a ZK-ID: a uniformly random element id: Scalar
-- this is a secret the user must not reveal to anyone because it is an analogue of its private key.
There is (optionally) a special party -- a Registrar -- whose role is to register users in the shielder so that they are allowed to create accounts. The Registrar maintains an offchain database of users that are verified. There could be one Registrar, multiple or none, depending on the setup.
Each registrar holds a ECDSA "registrar key" whose public counterpart is well known (stored for instance in the shielder smart contract to verify signatures issued by the registrar). This key can be rotated, but the simplified design below does not take that into account.
A user with ZK-ID id
registers offchain with a Registrar by going through an onboarding process (depending on the specific Registrar) and providing the Registrar with Com(id)
-- a commitment to its id
. In the simplest case the commitment can be just c = Com(id, r) = hash(id, r)
where r
is a random salt generated by the user (which the user needs to store). The Registrar then marks the fact or registration with a particular Com(id)
in its internal database.
A registration, by default, is valid for a certain, limited amount of time. After the time passes the user needs to perform a refresh procedure with the Registrar, which might involve repeating some checks, depending on the specific Registrar.
The user can receive a certificate of registration (with a particular expiration date) from a Registrar using the following procedure:
The user holding id
contacts the Registrar with whom it previously registered.
The registrar holds c=Com(id, r)
-- the commitment to the id
created by the user, but it doesn't know the randomness r
Denote by date
the expiration timestamp of the registration.
The Registrar generates a certificate for the user using the following steps:
Generate randomness r'
(optionally this randomness might be contributed by the user instead)
Compute reg_payload = hash(c, date, r')
Compute the ECDSA signature s
of payload
using the "registrar key"
The registrar provides the user with s, date, r'
. Apart from that, the user knows c
because they have generated it in the first place.
The user can then use the "certificate" in the form of the signature s
along with the reg_payload
(whose content is hidden using r'
) to certify on-chain that they hold a registered id
with a particular expiration date. In practice the payload is used as a public input to a particular zk-relation, and the signature s
is verified in the plain.
After a user has registered its ZK-ID with a registrar it is allowed to create its note (initialize empty account) in the Shielder.
Given the above we are ready to describe the new_note
transaction
Once a note is initially created the user will keep updating it (spending it and creating a new one) and the information of the user's id
is persisted within the note. In the above we have also introduced nullifier_create_set
-- a new storage item in shielder
that allows us to make sure each id
has created just one note.
Refresh the id
with the Registrar. This happens by sending a refresh_id
transaction that allows to bump the expiration date based on a new certificate from the Registrar.
In we describe how the information about id
in the note can be used to add a security mechanism to deanonymize bad actors.
With zk ids, there is one additional check that must be introduced in the R_update_note
relation in , namely that the id has not expired (current_timestamp < date
in the note). In case the note has expired, the user is not allowed to transact within the shielder anymore. It has two options then:
If the user doesn't want that, or the Registrar refuses to refresh the id
, then user is allowed to withdraw all the assets, but only withdrawal is possible. Such withdrawal will also cause mandatory deanonymization using the anonymity revoking mechanism, as described in .