plonky2-crypto-gadgets/ecgfp5/src/elgamal.rs
ecgfp5/src/elgamal.rsRaw
1use num::bigint::BigUint;
2use pod2::backends::plonky2::primitives::ec::curve::{GROUP_ORDER, Point};
3
4use crate::ECGFP5SecretKey;
5
6pub mod circuit;
7
8/// ElGamal encryption on EcGFp5
9pub fn elgamal_encrypt(pk: Point, nonce: &BigUint, msg: Point) -> (Point, Point) {
10 assert!(nonce < &GROUP_ORDER);
11 let nonce_times_gen = nonce * Point::generator();
12 let nonce_times_pk = nonce * pk;
13 (nonce_times_gen, msg + nonce_times_pk)
14}
15
16/// ElGamal decryption on EcGFp5
17pub fn elgamal_decrypt(sk: ECGFP5SecretKey, ct: (Point, Point)) -> Point {
18 let nonce_times_pk = &sk.0 * ct.0;
19 ct.1 + nonce_times_pk.inverse()
20}
21
22#[cfg(test)]
23mod tests {
24 use num_bigint::RandBigInt;
25 use pod2::backends::plonky2::primitives::ec::curve::{GROUP_ORDER, Point};
26 use rand::rngs::OsRng;
27
28 use crate::elgamal::{ECGFP5SecretKey, elgamal_decrypt, elgamal_encrypt};
29
30 #[test]
31 fn round_trip_encryption() {
32 (0..100).for_each(|_| {
33 let sk = ECGFP5SecretKey::rand();
34 let pk = sk.public_key();
35
36 let msg = Point::new_rand_from_subgroup();
37 let nonce = OsRng.gen_biguint_below(&GROUP_ORDER);
38
39 let encrypted_msg = elgamal_encrypt(pk, &nonce, msg);
40 let decrypted_msg = elgamal_decrypt(sk, encrypted_msg);
41
42 assert_eq!(msg, decrypted_msg);
43 })
44 }
45}