Skip to content

Multiparty Computation

Multiparty computation allows several parties to participate in a computation with their respective secret keys. Every party has its own secret key and every single secret key is required to decrypt an encrypted data. This makes collaborative data processing possible without the risk of the raw data being exposed. This document explains in a step-by-step manner how to do a multiparty computation.

A. Create Multiparty Secret Key and Multiparty Public Key

In multiparty computation, public keys are generated differently.

  • step 1: A common public key is generated for all users by the coordinator.
  • step 2: User 1 generates its own individual public key from the common public key and its private secret key.
  • step 3: User 2 does the exact same thing.
  • step 4: They both share with the coordinator the two newly generated individual public keys. Using the common public key and all the shared personal public keys, the multiparty public key can finally be generated.

Please check out the data structure document if you want more details about those special types of multiparty public keys.

Step 1: The coordinator generates the common public key

from desilofhe import Engine

common_engine = Engine(use_multiparty=True)
public_key_a = common_engine.create_public_key_a()

Step 2: User 1 generates a secret key and a public key

from desilofhe import Engine

engine1 = Engine(use_multiparty=True)

secret_key1 = engine1.create_secret_key()
# User 1's individual public key
public_key_b1 = engine1.create_public_key_b(secret_key1, public_key_a)

Step 3: User 2 generates a secret key and a public key

from desilofhe import Engine

engine2 = Engine(use_multiparty=True)

secret_key2 = engine2.create_secret_key()
# User 2's individual public key
public_key_b2 = engine2.create_public_key_b(secret_key2, public_key_a)

Step 4: The coordinator generates the common public key

public_key = common_engine.create_multiparty_public_key([public_key_b1, public_key_b2], public_key_a)

B. Encryption in Multiparty Computation

In multiparty computation, encryption is performed using the public key.

data = [1, 2, 3]
encrypted = engine1.encrypt(data, public_key)

C. Decryption in Multiparty Computation

In multiparty computation, secret keys must not be exposed, so when a decryption is needed, each user generates a decrypted share using its own secret key (steps 1 and 2). These decrypted shares are combined to decrypt the data (step 3). Note that a common public key is required as explained in section B.

Step 1: User 1 generates a decrypted share using its own secret key

decrypted_share1 = engine1.individual_decrypt(encrypted, secret_key1)

Step 2: User 2 generates a decrypted share using its own secret key

decrypted_share2 = engine2.individual_decrypt(encrypted, secret_key2)

Step 3: The coordinator decrypts the data using the decrypted shares

decrypted = common_engine.multiparty_decrypt(encrypted, [decrypted_share1, decrypted_share2])

D. Create Multiparty Relinearization Key

Using the shared public key, each participant generates its own individual relinearization key (steps 1 and 2) and shares it with the coordinator. Finally, the individual relinearization keys are combined to create a common relinearization key (step 3). Note that a common public key is required as explained in section A.

Step 1: User 1 generates an individual relinearization key

relinearization_key1 = engine1.create_individual_relinearization_key(secret_key1, public_key)

Step 2: User 2 generates an individual relinearization key

relinearization_key2 = engine2.create_individual_relinearization_key(secret_key2, public_key)

Step 3: The coordinator generates the common relinearization key

relinearization_key = common_engine.create_multiparty_relinearization_key([relinearization_key1, relinearization_key2])

E. Multiplication in Multiparty Computation

In multiparty computation, multiplications are performed using the common relinearization key (described in section D). This operations can be done by anyone, including the coordinator. Note that encrypted messages are needed as detailed in section B.

multiplied = engine1.multiply(encrypted1, encrypted2, relinearization_key)

F. Create Multiparty Fixed Rotation Key

Using the shared public key, each user generates a individual fixed rotation key and shares it with the coordinator (step 1 and 2). These individual fixed rotation keys are then used to create a common fixed rotation key (step 3). Note that a common public key is required as explained in section A. With the common fixed rotation key, it is now possible to apply a rotation on any ciphertext which was encrypted with the common public key.

Step 1: User 1 generates an individual fixed rotation key

fixed_rotation_key1 = engine1.create_individual_fixed_rotation_key(secret_key1, public_key, delta = 2)

Step 2: User 2 generates an individual fixed rotation key

fixed_rotation_key2 = engine2.create_individual_fixed_rotation_key(secret_key2, public_key, delta = 2)

Step 3: The coordinator generates the common fixed rotation key

fixed_rotation_key = common_engine.create_multiparty_fixed_rotation_key([fixed_rotation_key1, fixed_rotation_key2])

G. Create Multiparty Rotation Key

Using the shared public key (generated in section A), each user generates its own individual rotation key (step 1 and 2) and shares it with the coordinator. These individual rotation keys are then used to create a common rotation key (step 3). With the common rotation key, it is now possible to apply a rotation on any ciphertext which was encrypted with the common public key.

Step 1: User 1 generates an individual rotation key

rotation_key1 = engine1.create_individual_rotation_key(secret_key1, public_key)

Step 2: User 2 generates an individual rotation key

rotation_key2 = engine2.create_individual_rotation_key(secret_key2, public_key)

Step 3: The coordinator generates the common rotation key

rotation_key = common_engine.create_multiparty_rotation_key([rotation_key1, rotation_key2])

H. Create Multiparty Conjugation Key

Using the shared public key (generated in section A), each user generates its own individual conjugation key (step 1 and 2) and shares it with the coordinator. These individual conjugation keys are then used to create a common conjugation key (step 3). With the common conjugation key, it is now possible to apply a conjugation on any ciphertext which was encrypted with the common public key.

Step 1: User 1 generates an individual conjugation key

conjugation_key1 = engine1.create_individual_conjugation_key(secret_key1, public_key)

Step 2: User 2 generates an individual conjugation key

conjugation_key2 = engine2.create_individual_conjugation_key(secret_key2, public_key)

Step 3: The coordinator generates the common conjugation key

conjugation_key = common_engine.create_multiparty_conjugation_key([conjugation_key1, conjugation_key2])