Skip to main content
Version: v2.x

Hashing and Encryption

Hash Functions

MACI uses the Poseidon hash function, which is proven to be very efficient in ZK applications. Poseidon accepts nn inputs and produces 1 output:

y=poseidonn([x1,x2,...,xn])y = poseidon_n([x_1, x_2, ..., x_n])

Also, SHA256 is used to compress public inputs to a circuit into a single field element in the finite field FF mod pp.

Message Encryption

In order to encrypt messages, MACI uses Poseidon in DuplexSponge mode. This provides an encryption function and a decryption function:

  • CC as poseidonEncrypt(ks[0],ks[1],N,l,t[])poseidonEncrypt(k_s[0], k_s[1], N, l, t[])
  • poseidonDecrypt(ks[0],ks[1],N,l,C)poseidonDecrypt(k_s[0], k_s[1], N, l, C)

In more details,

  • ksk_s is the shared key, a point on the Baby Jubjub curve
  • NN is the nonce, which we hardcode to 0
  • ll is the length of the plaintext t[]t[]

The implementation can be found here.

Shared Key Generation

The ECDH algorithm is used to generate a shared key, which is then used to encrypt each message. This allows to create messages which are only decryptable by the coordinator and the person sending the message.

In more details:

  • The coordinator's public key cPkcPk is known to all. Their private key cSkcSk is secret.

  • When the user publishes a message (i.e. casts a vote), they generate an ephemeral keypair with private key eSkeSk and public key ePkePk.

  • The user generates the shared key kk using the coordinator's public key cPkcPk and the user's ephemeral private key eSkeSk.

  • The user encrypts the command and signature with kk to form a message.

  • The user sends their ephemeral public key ePkePk along with the ciphertext. The coordinator can recover the same shared key using their private key cSkcSk and the given ephemeral public key ePkePk.