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