Anonymity Revokers
Anonymity Revoker (AR in short) is a role that helps protecting the Shielder from bad actors. The main idea is that an AR would deanonymize all actions withing the Shielder of a recognized bad actor. The typical scenario we have in mind here is as follows:
Illicit funds are detected on chain that have been used to interact with the Shielder. For instance the funds come from a well known hack.
A specific Shielder transaction, say a deposit, is determined to be using illicit funds.
A governance process decides whether to deanonymize the user behind this deposit. And if it decides YES, then a request to deanonymize is sent to the AR.
The AR reveals the transaction, and as a consequence (because of how the solution is built technically) this allows everyone to see the details of all other transactions performed by the illicit user, as if they were not using the Shielder at all.
Anonymity Revoker Key
The AR holds a private key AR_sk
for asymmetric encryption and the corresponding public key AR_pk
is a known parameter of the Shielder. The encryption scheme in use must be snark-friendly. Indeed, each transaction will need to include proofs of statements of the form
where m
is some private input and c
is public input.
User Transactions
For a ZK-ID id
we define by key(id)
a procedure key: Scalar -> Scalar
that produces a symmetric encryption key out of the id
. The key
map should be one-way. The simplest example would be to use key(id) = hash(id)
but there might be other constraints that might force use to use a different key derivation.
Whenever a user makes a transaction tx
in the shielder (that is otherwise be fully anonymous) it includes two additional encrypted pieces of data in it:
mac = (r, hash(r, key(id))) : (Scalar, Scalar)
-- the HMAC "signature" of the user under a random nonce. This is to be able to identify the user's transactions among all transaction knowingkey(id)
.e_key = Enc(AR_pk, key(id))
-- this is the encryptedkey
of the usere_op = SymEnc(key(id), op_priv)
-- this is an encryption of the private part of the operationop_priv: OpPriv
the user is performing on its account, encrypted using a symmetric (snark-friendly) encryption scheme (see SNARK-friendly Symmetric Encryption) using keykey(id)
Modification to Transactions
Note that adding the encryptions to the transaction requires some changes to what we introduced in Notes and Accounts -- for completeness we repeat the parts that change including the necessary modifications. The main idea though is simple: in the update_note
transaction we need to put constraints checking the correctness of encryption and forming the mac.
Revoking Anonymity
In case the anonymity revocation procedure is triggered on a transaction tx
. The AR publicly decrypts the e_key
field of the transaction tx
revealing the key
which the user uses to encrypt all the operations related to its account. Now, by scanning all the shielder transactions from start, each user can decrypt all transactions from the user who created tx
. The way it is done is by inspecting the mac
attached to each transaction, if mac = (m_0, m_1)
then by checking the condition
m_1 == hash(m_0, key)
it is possible to verify if the transaction came from the deanonymized user. Using this idea, one can find
the transaction that created the first note of this user
one can find each operation
op
that was applied to this users' account, this is by combiningop_pub
that is public andop_priv
that is encrypted usingkey
Using the above one can recover the complete history of this users' account and in particular recover the current state, and see all the new transactions of the user in the plain.
Last updated