//! El-Gamal encryption on a prime-order cyclic group.
dbg(GEN, ORDER);
gen = || {
sk = rand_scalar();
#{ sk, pk: GEN ^ sk }
};
encrypt = |message, pk| {
r = rand_scalar();
shared_secret = pk ^ r;
#{ R: GEN ^ r, B: message * shared_secret }
};
decrypt = |{ R, B }, sk| {
shared_secret = R ^ sk;
B / shared_secret
};
// Test!
{ sk, pk } = gen();
5.while(|i| i != 0, |i| {
message = GEN ^ rand_scalar();
dbg(message);
encrypted = message.encrypt(pk);
dbg(encrypted);
assert_eq(encrypted.decrypt(sk), message);
i - 1
});
// Advanced testing making use of partial homomorhicity of encryption.
ONE = GEN ^ 0;
encrypt_and_combine = |messages, pk| {
messages.map(|msg| msg.encrypt(pk)).fold(
#{ R: ONE, B: ONE },
|enc_x, enc_y| enc_x * enc_y,
)
};
messages = (1, 2, 3, 4, 5).map(|_| GEN ^ rand_scalar());
assert_eq(
encrypt_and_combine(messages, pk).decrypt(sk),
messages.fold(ONE, |acc, msg| acc * msg)
);