From ea28bbf30b7e41fbbf63833f7425a8cf43448f12 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Fri, 9 Jun 2023 00:15:17 +0200 Subject: [PATCH] python integration of ecc, code cleanup --- Cargo.toml | 2 +- src/lib.rs | 2 + src/math/ecc.rs | 185 ++++++++++++++++++++++++++++++-------------- src/math/gallois.rs | 21 ++++- 4 files changed, 148 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 36c8e59..3050054 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "plexcryptool" authors = ["Christoph J. Scherr "] -version = "0.2.9" +version = "0.2.10" edition = "2021" readme = "README.md" description = "Various tools for use with math and cryptology, includes executable and a library." diff --git a/src/lib.rs b/src/lib.rs index 3689bf3..7dc7791 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,8 @@ fn register_math_module(py: Python, parent_module: &PyModule) -> PyResult<()> { math_module.add_function(wrap_pyfunction!(math::gcd::alt_egcd, math_module)?)?; math_module.add_function(wrap_pyfunction!(math::factorise::prime_factors , math_module)?)?; math_module.add_class::()?; + math_module.add_class::()?; + math_module.add_class::()?; parent_module.add_submodule(math_module)?; Ok(()) } diff --git a/src/math/ecc.rs b/src/math/ecc.rs index 22d346c..fc35c89 100644 --- a/src/math/ecc.rs +++ b/src/math/ecc.rs @@ -12,14 +12,15 @@ use crate::cplex::printing::seperator; use super::gallois::GalloisField; -use std::{ops::{Mul, Neg}, fmt::{Debug, Display}, f32::consts::PI}; +use std::fmt::Debug; use num::{Integer, Unsigned, NumCast}; use bitvec::prelude::*; -use pyo3::prelude::*; +use pyo3::{prelude::*, exceptions::PyValueError}; +#[pyclass] #[derive(Debug, Clone, Eq, PartialEq)] #[allow(non_snake_case)] /// represent a specific eliptic curve @@ -69,7 +70,7 @@ impl ElipticCurve { Check for Diskriminante passed", field.reduce::<_, u128>(d)); } - let mut infty = ElipticCurvePoint::new(0, 0, field, false); + let mut infty = ElipticCurvePoint::new(0, 0); infty.is_infinity_point = true; let infty = infty; let e = ElipticCurve { @@ -85,7 +86,7 @@ impl ElipticCurve { /// build a new point in the EC pub fn new_point(&self, r: u128, s: u128) -> Result { - let p = ElipticCurvePoint::new(r, s, self.field, self.verbose); + let p = ElipticCurvePoint::new(r, s); if self.verbose { println!("{p}") } @@ -103,13 +104,9 @@ impl ElipticCurve { 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: u128 = num::cast::AsPrimitive::as_(r); let s: u128 = num::cast::AsPrimitive::as_(s); let res = (s.pow(2) as u128) - (r.pow(3) as u128) - (self.a * r) - self.b; @@ -123,6 +120,10 @@ impl ElipticCurve { } pub fn check_point(&self, p: ElipticCurvePoint, verbose: bool) -> bool { + if p.is_infinity_point { + println!("p is infinity: {p}"); + return true; + } let mut valid = true; // insert into poly @@ -158,23 +159,20 @@ impl ElipticCurve { println!("adding {p1} + {p2}"); seperator(); } - if p1.field != p2.field { - return Err(String::from("Points are not on the same field")); - } - if !self.check_point(p1, self.verbose) { + if !self.check_point(p1, false) { return Err(String::from("{p1} is not a valid point")); } - if !self.check_point(p2, self.verbose) { + if !self.check_point(p2, false) { return Err(String::from("{p2} is not a valid point")); } - if p1.field.prime_base { + if self.field.prime_base { // verbisity stuff - if self.verbose { - println!("{} = {}; {} = -{} = {} <=> {}", - p1.r, p2.r, p1.s, p2.s, self.neg(p2).s, - p1.r == p2.r && p1.s == self.neg(p2).s, - ); - } + //if self.verbose { + // println!("{} = {}; {} = -{} = {} <=> {}", + // p1.r, p2.r, p1.s, p2.s, self.neg(p2).s, + // p1.r == p2.r && p1.s == self.neg(p2).s, + // ); + //} // case 1: both infty if p1.is_infinity_point && p2.is_infinity_point { if self.verbose { @@ -204,14 +202,14 @@ impl ElipticCurve { let m: i128 = m as i128; if self.verbose { println!("m = [s_2 - s_1]/[r_2 - r_1] = [{} - {}]/[{} - {}] = {} = {}", - p2.s, p1.s, p2.r, p1.r, m, p1.field.reduce::<_, u128>(m)) + p2.s, p1.s, p2.r, p1.r, m, self.field.reduce::<_, u128>(m)) } let m: i128 = self.field.reduce(m); let r3 = m.pow(2) - p1.r as i128 - p2.r as i128; if self.verbose { println!("r_3 = m² - r_1 - r_2 = {} - {} - {} = {} = {}", - m.pow(2), p1.r, p2.r, r3, p1.field.reduce::<_, u128>(r3)); + m.pow(2), p1.r, p2.r, r3, self.field.reduce::<_, u128>(r3)); } let r3 = self.field.reduce::<_, u128>(r3); @@ -225,9 +223,9 @@ impl ElipticCurve { let s3 = self.field.reduce::<_, u128>(s3) as i128; if self.verbose { println!("-s_3 = - {s3} = {}", self.field.reduce::<_, u128>(-s3)); + println!("Q = ({}, {})", r3, s3); } - let p3 = ElipticCurvePoint::new(r3, self.field.reduce::<_, u128>(-s3), - self.field, self.verbose); + let p3 = self.new_point(r3, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist"); if self.verbose { seperator(); @@ -286,19 +284,18 @@ impl ElipticCurve { let r3: i128 = self.field.reduce::<_, i128>(m.pow(2)) - p1.r as i128 - p2.r as i128; if self.verbose { println!("r_3 = m² - r_1 - r_2 = {} - {} - {} = {} = {}", - m.pow(2), p1.r, p2.r, r3, p1.field.reduce::<_, u128>(r3)); + m.pow(2), p1.r, p2.r, r3, self.field.reduce::<_, u128>(r3)); } let r3: i128 = self.field.reduce(r3); let s3: i128 = m.pow(3) - 2*m*p1.r as i128 - m*p2.r as i128 + p1.s as i128; - if self.verbose || p2.verbose { + if self.verbose { println!("s_3 = m³ − 2*m*r_1 − m*r_2 + s1 = {} - 2*{m}*{} - {m}*{} + {} = \ {} = {}", m.pow(3), p1.r, p2.r, p1.s, s3, self.field.reduce::<_, u128>(s3)); } let s3: i128 = self.field.reduce(s3); - let p3 = ElipticCurvePoint::new(r3 as u128, self.field.reduce::<_, u128>(-s3), - self.field, self.verbose); + let p3 = self.new_point(r3 as u128, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist in curve"); if self.verbose { seperator(); @@ -337,7 +334,7 @@ impl ElipticCurve { T: Debug, T: Unsigned, { - if !self.check_point(g, self.verbose) { + if !self.check_point(g, false) { return Err(String::from("invalid point")); } let t: usize = num::cast(t).unwrap(); @@ -362,7 +359,6 @@ impl ElipticCurve { return Ok(h); } for bit in t_bits { - dbg!(&index); if index == l { if self.verbose { println!("h_{index} = {h}") @@ -390,12 +386,85 @@ impl ElipticCurve { } } +#[pymethods] +impl ElipticCurve { + #[new] + pub fn py_new(field: GalloisField, a: i128, b: i128, verbose: bool) -> PyResult { + match Self::new(field, a, b, verbose) { + Ok(v) => {return Ok(v)}, + Err(e) => { + let py_e = PyValueError::new_err(e.to_string()); + return Err(py_e) + } + } + } + + #[pyo3(name="new_point")] + pub fn py_new_point(&self, r: u128, s: u128) -> PyResult { + match self.new_point(r, s) { + Ok(v) => {return Ok(v)}, + Err(e) => { + let py_e = PyValueError::new_err(e.to_string()); + return Err(py_e) + } + } + } + + #[pyo3(name="poly")] + pub fn py_poly(&self, x: i128, y: i128) -> i128 { + self.poly(x, y) + } + + #[pyo3(name="check_point", signature=(p, verbose = true))] + pub fn py_check_point(&self, p: ElipticCurvePoint, verbose: bool) -> bool { + self.check_point(p, verbose) + } + + #[pyo3(name="add")] + pub fn py_add(&self, p1: ElipticCurvePoint, p2: ElipticCurvePoint) + -> PyResult { + match self.add(p1, p2) { + Ok(v) => {return Ok(v)}, + Err(e) => { + let py_e = PyValueError::new_err(e.to_string()); + return Err(py_e) + } + } + } + + #[pyo3(name="neg")] + pub fn py_neg(&self, p: ElipticCurvePoint) -> ElipticCurvePoint { + self.neg(p) + } + + #[pyo3(name="mul")] + pub fn py_mul(&self, p1: ElipticCurvePoint, t: u128) + -> PyResult { + match self.mul(p1, t) { + Ok(v) => {return Ok(v)}, + Err(e) => { + let py_e = PyValueError::new_err(e.to_string()); + return Err(py_e) + } + } + } + + fn __str__(&self) -> PyResult { + Ok(format!("{}", self)) + } + + fn __repr__(&self) -> PyResult { + Ok(format!("{}", self)) + } +} + impl std::fmt::Display for ElipticCurve{ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "F(X, Y) = Y² - X³ -{}X - {}", self.a, self.b) } } +#[pyclass] #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// represent a specific eliptic curves point /// @@ -404,21 +473,27 @@ pub struct ElipticCurvePoint { r: u128, s: u128, is_infinity_point: bool, - field: GalloisField, - verbose: bool } +#[pymethods] impl ElipticCurvePoint { + #[new] /// create a new point - pub fn new(r: u128, s: u128, field: GalloisField, verbose: bool) -> ElipticCurvePoint { + pub fn new(r: u128, s: u128) -> ElipticCurvePoint { ElipticCurvePoint { r, s, is_infinity_point: false, - field, - verbose } } + + fn __str__(&self) -> PyResult { + Ok(format!("{}", self)) + } + + fn __repr__(&self) -> PyResult { + Ok(format!("{}", self)) + } } impl std::fmt::Display for ElipticCurvePoint { @@ -450,33 +525,27 @@ pub mod test { let ec = ElipticCurve::new(f, -3, 3, true).expect("ec cant be created"); // real points let p = vec![ - ElipticCurvePoint::new(0, 4, f, false), - ElipticCurvePoint::new(0, 9, f, false), - ElipticCurvePoint::new(1, 1, f, false), - ElipticCurvePoint::new(1, 12, f, false), - ElipticCurvePoint::new(4, 4, f, false), - ElipticCurvePoint::new(4, 9, f, false), - ElipticCurvePoint::new(5, 3, f, false), - ElipticCurvePoint::new(5, 10, f, false), - ElipticCurvePoint::new(7, 0, f, false), - ElipticCurvePoint::new(8, 6, f, false), - ElipticCurvePoint::new(9, 4, f, false), - ElipticCurvePoint::new(9, 9, f, false), - ElipticCurvePoint::new(11, 1, f, false), - ElipticCurvePoint::new(11, 12, f, false), + ec.new_point(0, 4 ).unwrap(), + ec.new_point(0, 9 ).unwrap(), + ec.new_point(1, 1 ).unwrap(), + ec.new_point(1, 1 ).unwrap(), + ec.new_point(4, 4 ).unwrap(), + ec.new_point(4, 9 ).unwrap(), + ec.new_point(5, 3 ).unwrap(), + ec.new_point(5, 10 ).unwrap(), + ec.new_point(7, 0 ).unwrap(), + ec.new_point(8, 6 ).unwrap(), + ec.new_point(9, 4 ).unwrap(), + ec.new_point(9, 9 ).unwrap(), + ec.new_point(11, 1 ).unwrap(), + ec.new_point(11, 12 ).unwrap(), ]; // random values, not part of the e, fc. let np = vec![ - ElipticCurvePoint::new(0, 5, f, false), - ElipticCurvePoint::new(1, 9, f, false), - ElipticCurvePoint::new(1, 4, f, false), + ec.new_point(0, 5).unwrap_err(), + ec.new_point(1, 9).unwrap_err(), + ec.new_point(1, 4).unwrap_err(), ]; - for i in p { - assert!(ec.clone().check_point(i, true)); - } - for i in np { - assert!(!ec.clone().check_point(i, true)); - } } #[test] diff --git a/src/math/gallois.rs b/src/math/gallois.rs index f71600d..a83496e 100644 --- a/src/math/gallois.rs +++ b/src/math/gallois.rs @@ -15,12 +15,12 @@ /// License: MIT /// Source: -use crate::{math::modexp::{self, modular_exponentiation_wrapper}, cplex::printing::seperator, math::modred::modred}; +use crate::{math::modexp, cplex::printing::seperator, math::modred::modred}; use core::fmt; use std::fmt::Debug; -use num::{Integer, NumCast, Signed, Unsigned}; +use num::{Integer, NumCast}; use pyo3::{prelude::*, exceptions::PyValueError}; @@ -391,6 +391,7 @@ impl GalloisField { self.cha = i; return i; } + } #[pymethods] @@ -458,6 +459,20 @@ impl GalloisField { } panic!("No order was found, but n is not 0 and all possibilities have been tried"); } + + fn __str__(&self) -> PyResult { + Ok(format!("{}", self)) + } + + fn __repr__(&self) -> PyResult { + Ok(format!("{}", self)) + } +} + +impl std::fmt::Display for GalloisField { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "F_{}", self.base) + } } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -482,7 +497,7 @@ pub mod test { assert_eq!(field.reduce::<_, u128>(i as u128), i); } - let field = GalloisField::new(16, true, None); + let _ = GalloisField::new(16, true, None); } #[test]