diff --git a/src/common/finite_field.rs b/src/common/finite_field.rs index 231a2a0..6fc57fd 100644 --- a/src/common/finite_field.rs +++ b/src/common/finite_field.rs @@ -1,4 +1,4 @@ -use std::{ops::{Add, Sub, Mul}, fmt::{self, Display}}; +use std::{ops::{Add, Sub, Mul, Div, Neg}, fmt::{self, Display}}; use bigdecimal::{BigDecimal, Zero}; @@ -16,10 +16,17 @@ macro_rules! ffe { }; } +#[macro_export] +macro_rules! ffeb { + ( $value: expr, $p: expr ) => { + FiniteFieldElement::new($value, $p) + }; +} + #[derive(Debug, Clone, PartialEq)] pub struct FiniteFieldElement { pub value: BigDecimal, - p: BigDecimal + pub p: BigDecimal } fn pmod(x: BigDecimal, y: BigDecimal) -> BigDecimal { @@ -73,6 +80,22 @@ impl Mul for FiniteFieldElement { } } +impl Div for FiniteFieldElement { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + Self::new(self.value / rhs.value, self.p) + } +} + +impl Neg for FiniteFieldElement { + type Output = Self; + + fn neg(self) -> Self::Output { + Self::new(-self.value, self.p) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/elliptic_curve/elliptic_curve.rs b/src/elliptic_curve/elliptic_curve.rs index df75b50..bef7caa 100644 --- a/src/elliptic_curve/elliptic_curve.rs +++ b/src/elliptic_curve/elliptic_curve.rs @@ -1,23 +1,85 @@ -use bigdecimal::BigDecimal; -use crate::common::finite_field::*; +use bigdecimal::{BigDecimal, FromPrimitive}; +use crate::{common::finite_field::*, b, ffeb, ffe}; +#[derive(Debug, Clone, PartialEq)] pub struct EllipticCurve { pub a: BigDecimal, pub b: BigDecimal, pub p: BigDecimal } +#[derive(Debug, Clone, PartialEq)] pub struct EllipticCurvePoint { pub x: FiniteFieldElement, - pub y: FiniteFieldElement + pub y: FiniteFieldElement, + pub infinity: bool } impl EllipticCurve { - pub fn add(lhs: EllipticCurvePoint, rhs: EllipticCurvePoint) -> EllipticCurvePoint { - lhs + pub fn add(self, lhs: EllipticCurvePoint, rhs: EllipticCurvePoint) -> EllipticCurvePoint { + if lhs.clone().x == rhs.x && rhs.y == -lhs.clone().y { + return EllipticCurvePoint { + x: ffe!(0, 1), + y: ffe!(0, 1), + infinity: true + } + } + + if lhs.infinity { + return rhs + } + + if rhs.infinity { + return lhs + } + + let (psi, phi) = if lhs == rhs { + let phi = Self::twice_phi(lhs.clone(), self.clone()); + let psi = Self::twice_psi(lhs.clone(), self); + + (phi, psi) + } else { + let phi = Self::add_phi(lhs.clone(), rhs.clone()); + let psi = Self::add_psi(lhs.clone(), rhs.clone()); + + (phi, psi) + }; + + EllipticCurvePoint { + x: phi.clone() * phi - lhs.x.clone() - rhs.x.clone(), + y: todo!(), + infinity: todo!(), + } } fn add_phi(a: EllipticCurvePoint, b: EllipticCurvePoint) -> FiniteFieldElement { - + (a.y - b.y) / (a.x - b.x) + } + + fn add_psi(a: EllipticCurvePoint, b: EllipticCurvePoint) -> FiniteFieldElement { + (a.x.clone() * b.y - b.x.clone() * a.y) / (a.x - b.x) + } + + fn twice_phi(a: EllipticCurvePoint, c: EllipticCurve) -> FiniteFieldElement { + let x = a.x.clone(); + let y = a.y.clone(); + let p = a.x.p.clone(); + ( + ffeb!(b!(3), p.clone()) * x.clone() * x + + ffeb!(c.a, p.clone()) + ) / ( + ffeb!(b!(2), p) * y + ) + } + + fn twice_psi(a: EllipticCurvePoint, c: EllipticCurve) -> FiniteFieldElement { + let p = a.x.p.clone(); + ( + ffeb!(b!(3), p.clone()) * a.x.clone() * a.x.clone() + + ffeb!(c.a, p.clone()) * a.x.clone() + - ffeb!(b!(2), p.clone()) * a.y.clone() * a.y.clone() + ) / ( + ffeb!(b!(2), p) * a.y + ) } }