I am trying to implement an electronic voting scheme which uses the exponential version of elgamal cryptosystem, voters encrypt their votes for each candidate and send them all to the ballot box. Now each ballot contains the encryption of either 0 or 1 for each candidate in a determined order, vote's validity gets checked by ZKP.
can I use exponential elgamal to encrypt the value 0? and why the following piece of code written in rust keeps giving me wrong decryption:
use babyjubjub_rs::*;
use ff::*;
use num_bigint::{BigInt};
use lazy_static::lazy_static;
pub type Fr = poseidon_rs::Fr;
lazy_static! {
//order of BN256 curve used in etherium
pub static ref Q: BigInt = BigInt::parse_bytes(
b"21888242871839275222246405745257275088548364400416034343698204186575808495617",10
)
.unwrap();
//base point(generator)
static ref B8: Point = Point {
x: Fr::from_str(
"5299619240641551281634865583518297030282874472190772894086521144482721001553",
)
.unwrap(),
y: Fr::from_str(
"16950150798460657717958625567821834550301663161624707787222815936182638968203",
)
.unwrap(),
};
//order of the curve
static ref ORDERfr: Fr = Fr::from_str(
"21888242871839275222246405745257275088614511777268538073601725287587578984328",
)
.unwrap();
pub static ref ORDER: BigInt = BigInt::parse_bytes(
b"21888242871839275222246405745257275088614511777268538073601725287587578984328",10
).unwrap();
}
fn main{
let a: BigInt = BigInt::parse_bytes(b"4692761135892239337928260396782819307561300324840260345581292484414243101484", 10).unwrap();
let A: Point = B8.mul_scalar(&a);
let m:BigInt = BigInt::parse_bytes(b"0",10).unwrap();
let M:Point = B8.mul_scalar(&m);
let k = new_key().scalar_key();
let (K,C) = elgamal_encrypt(&A,M,k);
let MM:Point = elgamal_decrypt(&a,K,C);
}
fn elgamal_encrypt(public_key:&Point, message:Point, ephemeral_key:BigInt) -> (Point,Point){
let K:Point = B8.mul_scalar(&ephemeral_key);
let S:Point = public_key.mul_scalar(&ephemeral_key);
let C:Point = (S.projective()).add(&message.projective()).affine();
return (K,C);
}
fn elgamal_decrypt(private_key:&BigInt, K:Point, C:Point) -> Point{
let mut S:Point = K.mul_scalar(&private_key);
S.y.negate();
let M:Point = C.projective().add(&S.projective()).affine();
return M;
}
I've used the formula explained here to implement the algorithm and checked it multiple times with different messages.