use crate::{
group::edwards25519::SuiteEd25519, util::random::RandStream, Group, Point, Random, Scalar,
};
use anyhow::Result;
use core::str::from_utf8;
pub fn el_gamal_encrypt<GROUP: Group>(
group: GROUP,
pubkey: &GROUP::POINT,
message: &[u8],
) -> (GROUP::POINT, GROUP::POINT, Vec<u8>) {
let m = group
.point()
.embed(Some(message), &mut RandStream::default());
let mut max = group.point().embed_len();
if max > message.len() {
max = message.len()
}
let remainder = message[max..].to_vec();
let k = group.scalar().pick(&mut RandStream::default()); let k_p = group.point().mul(&k, None); let s = group.point().mul(&k, Some(pubkey)); let c = s.clone().add(&s, &m); (k_p, c, remainder)
}
pub fn el_gamal_decrypt<GROUP: Group>(
group: GROUP,
prikey: &<GROUP::POINT as Point>::SCALAR,
k: GROUP::POINT,
c: GROUP::POINT,
) -> Result<Vec<u8>> {
let s = group.point().mul(prikey, Some(&k)); let p = group.point();
let m = p.sub(&c, &s); Ok(m.data()?)
}
#[test]
fn example_el_gamal_encryption() {
let suite = SuiteEd25519::new_blake3_sha256_ed25519();
let a = suite.scalar().pick(&mut suite.random_stream()); let a_p = suite.point().mul(&a, None);
let m = "The quick brown fox".as_bytes();
let (k, c, _) = el_gamal_encrypt(suite, &a_p, m);
let dec_res = el_gamal_decrypt(suite, &a, k, c);
if dec_res.is_err() {
panic!("decryption failed: {}", dec_res.err().unwrap())
}
let mm = dec_res.unwrap();
if from_utf8(&mm).unwrap() != from_utf8(m).unwrap() {
panic!(
"decryption produced wrong output: {}",
from_utf8(&mm).unwrap()
);
}
println!("Decryption succeeded: {}", from_utf8(&mm).unwrap())
}