Skip to content

ewynx/leo-elgamal

Folders and files

NameName
Last commit message
Last commit date
Oct 21, 2023
Oct 21, 2023
Oct 21, 2023
Oct 21, 2023
Oct 21, 2023
Oct 21, 2023

Repository files navigation

El Gamal Homomorphic Encryption in Leo

This repository contains an implementation of the ElGamal encryption scheme in Leo. ElGamal is a public-key cryptosystem that provides secure encryption and supports homomorphic operations on ciphertexts.

Overview El Gamal

Key Generation

We have prime p (see docs about field elements) and generator g = 22 (see here).

  • Sample a private key priv_key and compute public key pub_key.

Encryption

  • Choose a random k (here, we provide it as input as we don't have a RNG)
  • Compute C1 = g^k mod p and C2 = (m * pub_key^k) mod p.

Decryption

  • Calculate s_a = (C1^priv_key)^(-1) mod p.
  • Decrypt with m = (C2 * s_a) mod p.

Homomorphic Multiplication

  • Multiply ciphertexts (C1_1, C2_1) and (C1_2, C2_2) like this (C1_1 * C1_2, C2_1 * C2_2). This multiplies the plaintexts, encrypted.

When you decrypt this resulting ciphertext, the outcome is the multiplication of input messages.

Testing

Test 1 - All random values

Using PARI/GP random(8444461749428370424248824938781546531375899335154063827935233455917409239041)

m1 = 3177328874216172998069933727674842583425142197792604746898916331347613098227field
k1 = 7788669533474620218943169245892310534571119762675803628366628629491833959872field

m2 = 7392385298686921874454720710640332676910208501264821737459763253801297566260field
k2 = 5134642952836080535142054789475428226920331649739086847970712717638629145195field
  1. Test keypair. Priv key obtained from PARI/GP and public key calculated accordingly
  • pub_key = 1202779357084265799172575109162116407510522098349359838939772755638433935334field
  • priv_key = 8272198081443673477747743735279492263844137663249768316564672355525125340702field
leo run get_pub_key 8272198081443673477747743735279492263844137663249768316564672355525125340702field
  1. Encrypt messages
leo run encrypt 3177328874216172998069933727674842583425142197792604746898916331347613098227field 1202779357084265799172575109162116407510522098349359838939772755638433935334field 7788669533474620218943169245892310534571119762675803628366628629491833959872field
# {
#   c1: 116575650185516315037706915534870957945861122734470769193284709558551905075field,
#   c2: 4471211774191713085171237206082550903057017645511837250896078589929639426138field
# }

leo run encrypt 7392385298686921874454720710640332676910208501264821737459763253801297566260field 1202779357084265799172575109162116407510522098349359838939772755638433935334field 5134642952836080535142054789475428226920331649739086847970712717638629145195field
# {
#   c1: 8356500384850355260863030215464266805952907230053491489345348145061329671073field,
#   c2: 6497783301369533769463154618080480544198785069776245714420412729566178306251field
# }
  1. Multiply messages
leo run mult_ciphertexts "{
  c1: 116575650185516315037706915534870957945861122734470769193284709558551905075field,
  c2: 4471211774191713085171237206082550903057017645511837250896078589929639426138field
}" "{
  c1: 8356500384850355260863030215464266805952907230053491489345348145061329671073field,
  c2: 6497783301369533769463154618080480544198785069776245714420412729566178306251field
}"
#  {
#   c1: 4905016814170485075672822187469145847600627478371320601690326030471658137543field,
#   c2: 2262656180784385643118284026677859987588418961078216371132389931829390462001field
# }
  1. Decrypt
leo run decrypt "{
  c1: 4905016814170485075672822187469145847600627478371320601690326030471658137543field,
  c2: 2262656180784385643118284026677859987588418961078216371132389931829390462001field
}" 8272198081443673477747743735279492263844137663249768316564672355525125340702field
# 5933534467186704308506600189314596155202034203178335985155887746469840603067field

Check result in PARI/GP

Mod(3177328874216172998069933727674842583425142197792604746898916331347613098227*7392385298686921874454720710640332676910208501264821737459763253801297566260, 8444461749428370424248824938781546531375899335154063827935233455917409239041)
#  5933534467186704308506600189314596155202034203178335985155887746469840603067
#  Correct!

Test 2 - Random values and small values

Using PARI/GP random(8444461749428370424248824938781546531375899335154063827935233455917409239041)

m1 = 45678field
k1 = 5203042127358649340904750314466367793094507691418755756208128707314580522552field

m2 = 888field
k2 = 7854063782064912777947283892113100481529492690563337484262592127033185220460field

Test keypair

  • pub_key = 6400977530036418317775721924855138179897296576018842422808515401282150070936field
  • priv_key = 753004072685881823636366456603650587050591895244751816960546428819898446772field
leo run get_pub_key 753004072685881823636366456603650587050591895244751816960546428819898446772field
  1. Encrypt m1 under pub_key, using k1
leo run encrypt 45678field 6400977530036418317775721924855138179897296576018842422808515401282150070936field 5203042127358649340904750314466367793094507691418755756208128707314580522552field
# Result
# {
#   c1: 4545240134733908556125749800281845285389885560391618997728077370226461435670field,
#   c2: 4531182665311840178741949476500072442506888039781460179797884253108169739201field
# }

Encrypt m2 under pub_key, using k2
leo run encrypt 888field 6400977530036418317775721924855138179897296576018842422808515401282150070936field 7854063782064912777947283892113100481529492690563337484262592127033185220460field
# Result
# {
#   c1: 5271987784861258949073389714970410080411227307832527570448530128952551667122field,
#   c2: 2223377329472227322087938132587256302957818486055115575761851706179853533412field
# }
  1. Multiply the ciphertexts
leo run mult_ciphertexts "{
  c1: 4545240134733908556125749800281845285389885560391618997728077370226461435670field,
  c2: 4531182665311840178741949476500072442506888039781460179797884253108169739201field
}" "{
  c1: 5271987784861258949073389714970410080411227307832527570448530128952551667122field,
  c2: 2223377329472227322087938132587256302957818486055115575761851706179853533412field
}"
# Result
# {
#   c1: 4365548365631094310119356159764511142009651057404730790402062883678859712742field,
#   c2: 7275958970451129681359730432297163208322898972993243649458571762652227260057field
# }
  1. Decrypt
leo run decrypt "{
  c1: 4365548365631094310119356159764511142009651057404730790402062883678859712742field,
  c2: 7275958970451129681359730432297163208322898972993243649458571762652227260057field
}" 753004072685881823636366456603650587050591895244751816960546428819898446772field

# Result
# 40562064field = 45678 * 888
# Correct!

Test 3 - Small test values

Test keypair:

  • pub_key = 5153632field
  • priv_key = 5field
m1 = 2field
k1 = 123field

m2 = 3field
k2 = 456field
  1. Encrypt both messages m1, m2:
leo run encrypt 2field 5153632field 123field
# {
#   c1: 4281024143617973432384462541056021194822242417477687245451443563273154242473field,
#   c2: 1572711479132772385188434990553282722904522729883541792384696766198878997498field
# }

leo run encrypt 3field 5153632field 456field
# {
#   c1: 8219006186278527715773371608839031405611473808626602570518694310896630839794field,
#   c2: 7905567122759533570302126001762943316506837083107534363619137121591430247813field
# }
  1. Multiply the ciphertexts
leo run mult_ciphertexts "{
  c1: 4281024143617973432384462541056021194822242417477687245451443563273154242473field,
  c2: 1572711479132772385188434990553282722904522729883541792384696766198878997498field
}" "{
  c1: 8219006186278527715773371608839031405611473808626602570518694310896630839794field,
  c2: 7905567122759533570302126001762943316506837083107534363619137121591430247813field
}"

# Result
#  {
#   c1: 8382652612567042214492403753719299065156905393912387035871137815124637126753field,
#   c2: 7597951025613609547169088091808543498720626840350081699542403411289273624058field
# }
  1. Decrypt to get result
leo run decrypt "{
  c1: 8382652612567042214492403753719299065156905393912387035871137815124637126753field,
  c2: 7597951025613609547169088091808543498720626840350081699542403411289273624058field
}" 5field

# Result
# 6field <- multiplying the ciphertexts multiplies the plaintexts

Build Guide

To compile this Aleo program, run:

snarkvm build

To execute this Aleo program, run:

snarkvm run hello

leo run get_pub_key 5field

About

Implementation of ElGamal in Leo

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published