use crate::{
ff::FiniteField,
isogeny::{CurveIsogenies, PublicParameters},
utils::shake,
};
pub use crate::isogeny::{PublicKey, SecretKey};
use std::fmt::Debug;
#[derive(Clone)]
pub struct Message {
pub bytes: Vec<u8>,
}
impl Message {
pub fn from_bytes(bytes: Vec<u8>) -> Self {
Self { bytes }
}
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
}
#[derive(Clone)]
pub struct Ciphertext {
pub bytes00: Vec<u8>,
pub bytes01: Vec<u8>,
pub bytes02: Vec<u8>,
pub bytes1: Vec<u8>,
}
pub struct PKE<K> {
pub isogenies: CurveIsogenies<K>,
params: PublicParameters<K>,
}
impl<K: FiniteField + Clone + Debug> PKE<K> {
#[inline]
pub fn setup(params: PublicParameters<K>) -> Self {
Self {
isogenies: CurveIsogenies::init(params.clone()),
params,
}
}
#[inline]
pub fn gen(&self) -> Result<(SecretKey, PublicKey<K>), String> {
let sk3 = SecretKey::get_random_secret_key(self.params.keyspace3 as usize)?;
let pk3 = self.isogenies.isogen3(&sk3)?;
Ok((sk3, pk3))
}
#[inline]
pub fn enc(&self, pk: &PublicKey<K>, m: Message) -> Result<Ciphertext, String> {
let sk2 = SecretKey::get_random_secret_key(self.params.keyspace2 as usize)?;
let c0: PublicKey<K> = self.isogenies.isogen2(&sk2)?;
let j = self.isogenies.isoex2(&sk2, &pk)?;
let h = self.hash_function_f(j);
if h.len() != m.bytes.len() {
return Err(String::from("Incorrect Hash"));
}
let c1_bytes = Self::xor(&m.bytes, &h);
let (part1, part2, part3) = c0.into_bytes();
Ok(Ciphertext {
bytes00: part1,
bytes01: part2,
bytes02: part3,
bytes1: c1_bytes,
})
}
#[inline]
pub fn dec(&self, sk: &SecretKey, c: Ciphertext) -> Result<Message, String> {
let c0 = &PublicKey::from_bytes(&c.bytes00, &c.bytes01, &c.bytes02)?;
let j: K = self.isogenies.isoex3(sk, c0)?;
let h = self.hash_function_f(j);
if h.len() != c.bytes1.len() {
return Err(String::from("Incorrect Hash"));
}
let m = Self::xor(&h, &c.bytes1);
Ok(Message { bytes: m })
}
pub fn hash_function_f(&self, j: K) -> Vec<u8> {
shake::shake256(&j.into_bytes(), self.params.secparam / 8)
}
pub fn xor(input1: &[u8], input2: &[u8]) -> Vec<u8> {
input1
.iter()
.zip(input2.iter())
.map(|(x, y)| x ^ y)
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
isogeny::{sike_p434_params, sike_p503_params, sike_p610_params, sike_p751_params},
utils::strategy::*,
};
#[test]
fn test_pke_optim_p434() {
let params = sike_p434_params(
Some(P434_TWO_TORSION_STRATEGY.to_vec()),
Some(P434_THREE_TORSION_STRATEGY.to_vec()),
)
.unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_optim_p503() {
let params = sike_p503_params(
Some(P503_TWO_TORSION_STRATEGY.to_vec()),
Some(P503_THREE_TORSION_STRATEGY.to_vec()),
)
.unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_optim_p610() {
let params = sike_p610_params(
Some(P610_TWO_TORSION_STRATEGY.to_vec()),
Some(P610_THREE_TORSION_STRATEGY.to_vec()),
)
.unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_optim_p751() {
let params = sike_p751_params(
Some(P751_TWO_TORSION_STRATEGY.to_vec()),
Some(P751_THREE_TORSION_STRATEGY.to_vec()),
)
.unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_p434() {
let params = sike_p434_params(None, None).unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_p503() {
let params = sike_p503_params(None, None).unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_p610() {
let params = sike_p610_params(None, None).unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
#[test]
fn test_pke_p751() {
let params = sike_p751_params(None, None).unwrap();
let pke = PKE::setup(params.clone());
println!("[Debug] Key generation");
let (sk, pk) = pke.gen().unwrap();
let msg = Message::from_bytes(vec![0; params.secparam / 8]);
println!("[Debug] Encryption");
let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
println!("[Debug] Decryption");
let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
}
}