use crate::{ff::FiniteField, isogeny::PublicKey};
pub struct Curve<K> {
pub a: K,
pub c: K,
}
impl<K: FiniteField + Clone> Curve<K> {
pub fn clone(&self) -> Self {
Self {
a: self.a.clone(),
c: self.c.clone(),
}
}
#[inline]
pub fn from_coeffs(a: K, c: K) -> Self {
Self { a, c }
}
#[inline]
pub fn starting_curve() -> Curve<K> {
let one = K::one();
let two = one.add(&one);
let three = two.add(&one);
let six = three.add(&three);
Curve::from_coeffs(six, one)
}
#[inline]
pub fn curve_plus(&self) -> Curve<K> {
let one = K::one();
let two = one.add(&one);
let four = two.add(&two);
let a = two.mul(&self.c).add(&self.a);
let c = four.mul(&self.c);
Curve::from_coeffs(a, c)
}
#[inline]
pub fn curve_plus_minus(&self) -> Curve<K> {
let one = K::one();
let two = one.add(&one);
let a = two.mul(&self.c).add(&self.a);
let c = self.a.sub(&two.mul(&self.c));
Curve::from_coeffs(a, c)
}
#[inline]
pub fn j_invariant(&self) -> Result<K, String> {
let j = self.a.mul(&self.a); let t1 = self.c.mul(&self.c); let t0 = t1.add(&t1); let t0 = j.sub(&t0); let t0 = t0.sub(&t1);
let j = t0.sub(&t1); let t1 = t1.mul(&t1); let j = j.mul(&t1); let t0 = t0.add(&t0); let t0 = t0.add(&t0);
let t1 = t0.mul(&t0); let t0 = t0.mul(&t1); let t0 = t0.add(&t0); let t0 = t0.add(&t0);
t0.div(&j) }
#[inline]
pub fn from_public_key(pk: &PublicKey<K>) -> Result<Curve<K>, String> {
let (x_p, x_q, x_r) = (&pk.x1, &pk.x2, &pk.x3);
if x_p.is_zero() || x_q.is_zero() || x_r.is_zero() {
return Err(String::from("Incorrect public key!"));
}
let one = K::one();
let two = one.add(&one);
let four = two.add(&two);
let num = K::one()
.sub(&x_p.mul(&x_q))
.sub(&x_p.mul(&x_r))
.sub(&x_q.mul(&x_r));
let num = num.mul(&num);
let denom = four.mul(&x_p).mul(&x_q).mul(&x_r);
let frac = num.div(&denom)?;
let a = frac.sub(&x_p).sub(&x_q).sub(&x_r);
let c = one;
Ok(Curve::from_coeffs(a, c))
}
}