diff --git a/src/math/ecc.rs b/src/math/ecc.rs index 0245ef1..d3e2ecc 100644 --- a/src/math/ecc.rs +++ b/src/math/ecc.rs @@ -1,8 +1,10 @@ #![allow(dead_code)] -/// eliptic curve cryptography +use std::{ops::{Mul, Neg}, fmt::Debug}; + +/// eliptic curve cryptograp.s /// -/// This module implements structs and functionalities used for eliptic curve cryptography (ECC). -/// Do not expect it to actually be secure, I made this for cryptography lectures. +/// This module implements structs and functionalities used for eliptic curve cryptograp.s (ECC). +/// Do not expect it to actually be secure, I made this for cryptograp.s lectures. /// /// Author: Christoph J. Scherr /// License: MIT @@ -10,19 +12,11 @@ use super::gallois::GalloisField; +use num::Integer; use pyo3::prelude::*; -/// This is a very special math point, it does not really exist but is useful. -pub const INFINITY_POINT: ElipticCurvePoint = ElipticCurvePoint { - x: 0, - y: 0, - is_infinity_point: true, - verbose: false -}; - #[derive(Debug, Clone)] #[allow(non_snake_case)] -#[pyclass] /// represent a specific eliptic curve /// /// real curves not supported, only in Gallois Fields @@ -32,36 +26,56 @@ pub struct ElipticCurve { b: i128, points: Vec, verbose: bool, - INFINITY_POINT: ElipticCurvePoint, + INFINITY_POINT: Option } impl ElipticCurve { pub fn new(f: GalloisField, a: i128, b: i128, verbose: bool) -> Self { - let e = ElipticCurve { + let mut e = ElipticCurve { f, a, b, points: Vec::new(), verbose, - INFINITY_POINT + INFINITY_POINT: None }; + let infty = ElipticCurvePoint::new(0, 0, e.f); + e.INFINITY_POINT = Some(infty); return e; } - /// calculate a point for coordinates - pub fn poly(&self, x: i128, y: i128) -> i128 { - return y.pow(2) - x.pow(3) - (self.a * x) - self.b; + /// calculate a value for coordinates + pub fn poly(&self, r: T, s: T) -> i128 + where + T: Integer, + T: Mul, + T: Debug, + T: num::cast::AsPrimitive, + T: Neg + { + dbg!(&r); + dbg!(&s); + let r: i128 = num::cast::AsPrimitive::as_(r); + let s: i128 = num::cast::AsPrimitive::as_(s); + let res = s.pow(2) - r.pow(3) - (self.a * r) - self.b; + let res1 = self.f.reduce(res); + if self.verbose { + println!("F({}, {}) = {}² - {}³ - {} * {} - {} = {res} = {res1}", + r, s, s, r, self.a, r, self.b + ); + } + return res1 as i128; } pub fn check_point(self, p: ElipticCurvePoint) -> bool { let mut valid = true; - let r = self.f.reduce(self.poly(p.x, p.y)); + let res = self.f.reduce(self.poly(p.r, p.s)); if self.verbose { - println!("F({}, {}) = {}² - {}³ - {} * {} - {} = {r}", - p.x, p.y, p.y, p.x, self.a, p.x, self.b + println!("F({}, {}) = {}² - {}³ - {} * {} - {} = {res}", + p.r, p.s, p.s, p.r, self.a, p.r, self.b ) } - valid &= r == 0; + valid &= res == 0; return valid; } } @@ -72,15 +86,15 @@ fn test_check_point() { let ec = ElipticCurve::new(f, 1, 679, true); // real points let p = vec![ - ElipticCurvePoint::new(298, 531), - ElipticCurvePoint::new(600, 127), - ElipticCurvePoint::new(846, 176), + ElipticCurvePoint::new(298, 531, f), + ElipticCurvePoint::new(600, 127, f), + ElipticCurvePoint::new(846, 176, f), ]; - // random values, not part of the ec. + // random values, not part of the e, fc. let np = vec![ - ElipticCurvePoint::new(198, 331), - ElipticCurvePoint::new(100, 927), - ElipticCurvePoint::new(446, 876), + ElipticCurvePoint::new(198, 331, f), + ElipticCurvePoint::new(100, 927, f), + ElipticCurvePoint::new(446, 876, f), ]; for i in p { dbg!(&i); @@ -94,43 +108,72 @@ fn test_check_point() { #[derive(Debug, Clone, Copy)] -#[pyclass] /// represent a specific eliptic curves point pub struct ElipticCurvePoint { - x: i128, - y: i128, + r: i128, + s: i128, is_infinity_point: bool, - verbose: bool + field: GalloisField } impl ElipticCurvePoint { - pub fn new(x: i128, y: i128) -> Self { + pub fn new(r: i128, s: i128, field: GalloisField) -> ElipticCurvePoint { ElipticCurvePoint { - x, - y, + r, + s, is_infinity_point: false, - verbose: false + field } } - pub fn get_infinity_point() -> Self { - return INFINITY_POINT; - } - /// add two points - pub fn add(a: Self, b: Self) -> Self { - // TODO - panic!("TODO"); + pub fn add(self, point: Self) -> Result { + if self.field.cha != point.field.cha { + return Err(String::from("Points are not on the same field")); + } + if self.field.prime_base { + // case 1 both infty + if self.is_infinity_point && point.is_infinity_point { + return Ok(point); + } + // case 2 one is infty + else if self.is_infinity_point && !point.is_infinity_point { + return Ok(point); + } + else if !self.is_infinity_point && point.is_infinity_point { + return Ok(self); + } + // case 3 r_1 != r_2 + else if self.r != point.r { + panic!("TODO"); + } + // case 4 r_1 = r_2; s_1 = -s_2 + else if self.r == point.r && self.s == point.neg().s { + return Ok(Self::new(0, 0, self.field)); + } + + // how do we get here? + // this should never occur + else { + panic!("we dont know what to do in this case?") + } + } + else { + return Err(String::from("Only prime fields are supported currently")); + } } /// get negative of a point - pub fn neg(p: Self) -> Self { - // TODO - panic!("TODO"); + pub fn neg(self) -> Self { + return ElipticCurvePoint::new( + self.r, + self.field.reduce(-(self.s as i128)) as i128, + self.field + ); } - /// multiply a point by an integer - pub fn mul(n: u128, a: Self) -> Self { + /// multip.s a point by an integer + pub fn mul(self, n: u128) -> Self { // TODO panic!("TODO"); }