python integration of ecc, code cleanup

This commit is contained in:
Christoph J. Scherr 2023-06-09 00:15:17 +02:00
parent 8a0d41b134
commit ea28bbf30b
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
4 changed files with 148 additions and 62 deletions

View File

@ -1,7 +1,7 @@
[package] [package]
name = "plexcryptool" name = "plexcryptool"
authors = ["Christoph J. Scherr <software@cscherr.de>"] authors = ["Christoph J. Scherr <software@cscherr.de>"]
version = "0.2.9" version = "0.2.10"
edition = "2021" edition = "2021"
readme = "README.md" readme = "README.md"
description = "Various tools for use with math and cryptology, includes executable and a library." description = "Various tools for use with math and cryptology, includes executable and a library."

View File

@ -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::gcd::alt_egcd, math_module)?)?;
math_module.add_function(wrap_pyfunction!(math::factorise::prime_factors , math_module)?)?; math_module.add_function(wrap_pyfunction!(math::factorise::prime_factors , math_module)?)?;
math_module.add_class::<math::gallois::GalloisField>()?; math_module.add_class::<math::gallois::GalloisField>()?;
math_module.add_class::<math::ecc::ElipticCurve>()?;
math_module.add_class::<math::ecc::ElipticCurvePoint>()?;
parent_module.add_submodule(math_module)?; parent_module.add_submodule(math_module)?;
Ok(()) Ok(())
} }

View File

@ -12,14 +12,15 @@ use crate::cplex::printing::seperator;
use super::gallois::GalloisField; 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 num::{Integer, Unsigned, NumCast};
use bitvec::prelude::*; use bitvec::prelude::*;
use pyo3::prelude::*; use pyo3::{prelude::*, exceptions::PyValueError};
#[pyclass]
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
/// represent a specific eliptic curve /// represent a specific eliptic curve
@ -69,7 +70,7 @@ impl ElipticCurve {
Check for Diskriminante passed", field.reduce::<_, u128>(d)); 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; infty.is_infinity_point = true;
let infty = infty; let infty = infty;
let e = ElipticCurve { let e = ElipticCurve {
@ -85,7 +86,7 @@ impl ElipticCurve {
/// build a new point in the EC /// build a new point in the EC
pub fn new_point(&self, r: u128, s: u128) -> Result<ElipticCurvePoint, String> { pub fn new_point(&self, r: u128, s: u128) -> Result<ElipticCurvePoint, String> {
let p = ElipticCurvePoint::new(r, s, self.field, self.verbose); let p = ElipticCurvePoint::new(r, s);
if self.verbose { if self.verbose {
println!("{p}") println!("{p}")
} }
@ -103,13 +104,9 @@ impl ElipticCurve {
pub fn poly<T>(&self, r: T, s: T) -> i128 pub fn poly<T>(&self, r: T, s: T) -> i128
where where
T: Integer, T: Integer,
T: Mul,
T: Debug, T: Debug,
T: num::cast::AsPrimitive<u128>, T: num::cast::AsPrimitive<u128>,
T: Neg
{ {
dbg!(&r);
dbg!(&s);
let r: u128 = num::cast::AsPrimitive::as_(r); let r: u128 = num::cast::AsPrimitive::as_(r);
let s: u128 = num::cast::AsPrimitive::as_(s); 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; 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 { 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; let mut valid = true;
// insert into poly // insert into poly
@ -158,23 +159,20 @@ impl ElipticCurve {
println!("adding {p1} + {p2}"); println!("adding {p1} + {p2}");
seperator(); seperator();
} }
if p1.field != p2.field { if !self.check_point(p1, false) {
return Err(String::from("Points are not on the same field"));
}
if !self.check_point(p1, self.verbose) {
return Err(String::from("{p1} is not a valid point")); 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")); return Err(String::from("{p2} is not a valid point"));
} }
if p1.field.prime_base { if self.field.prime_base {
// verbisity stuff // verbisity stuff
if self.verbose { //if self.verbose {
println!("{} = {}; {} = -{} = {} <=> {}", // println!("{} = {}; {} = -{} = {} <=> {}",
p1.r, p2.r, p1.s, p2.s, self.neg(p2).s, // p1.r, p2.r, p1.s, p2.s, self.neg(p2).s,
p1.r == p2.r && p1.s == self.neg(p2).s, // p1.r == p2.r && p1.s == self.neg(p2).s,
); // );
} //}
// case 1: both infty // case 1: both infty
if p1.is_infinity_point && p2.is_infinity_point { if p1.is_infinity_point && p2.is_infinity_point {
if self.verbose { if self.verbose {
@ -204,14 +202,14 @@ impl ElipticCurve {
let m: i128 = m as i128; let m: i128 = m as i128;
if self.verbose { if self.verbose {
println!("m = [s_2 - s_1]/[r_2 - r_1] = [{} - {}]/[{} - {}] = {} = {}", 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 m: i128 = self.field.reduce(m);
let r3 = m.pow(2) - p1.r as i128 - p2.r as i128; let r3 = m.pow(2) - p1.r as i128 - p2.r as i128;
if self.verbose { if self.verbose {
println!("r_3 = m² - r_1 - r_2 = {} - {} - {} = {} = {}", 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); let r3 = self.field.reduce::<_, u128>(r3);
@ -225,9 +223,9 @@ impl ElipticCurve {
let s3 = self.field.reduce::<_, u128>(s3) as i128; let s3 = self.field.reduce::<_, u128>(s3) as i128;
if self.verbose { if self.verbose {
println!("-s_3 = - {s3} = {}", self.field.reduce::<_, u128>(-s3)); println!("-s_3 = - {s3} = {}", self.field.reduce::<_, u128>(-s3));
println!("Q = ({}, {})", r3, s3);
} }
let p3 = ElipticCurvePoint::new(r3, self.field.reduce::<_, u128>(-s3), let p3 = self.new_point(r3, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist");
self.field, self.verbose);
if self.verbose { if self.verbose {
seperator(); 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; let r3: i128 = self.field.reduce::<_, i128>(m.pow(2)) - p1.r as i128 - p2.r as i128;
if self.verbose { if self.verbose {
println!("r_3 = m² - r_1 - r_2 = {} - {} - {} = {} = {}", 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 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; 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}*{} + {} = \ 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)); m.pow(3), p1.r, p2.r, p1.s, s3, self.field.reduce::<_, u128>(s3));
} }
let s3: i128 = self.field.reduce(s3); let s3: i128 = self.field.reduce(s3);
let p3 = ElipticCurvePoint::new(r3 as u128, self.field.reduce::<_, u128>(-s3), let p3 = self.new_point(r3 as u128, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist in curve");
self.field, self.verbose);
if self.verbose { if self.verbose {
seperator(); seperator();
@ -337,7 +334,7 @@ impl ElipticCurve {
T: Debug, T: Debug,
T: Unsigned, T: Unsigned,
{ {
if !self.check_point(g, self.verbose) { if !self.check_point(g, false) {
return Err(String::from("invalid point")); return Err(String::from("invalid point"));
} }
let t: usize = num::cast(t).unwrap(); let t: usize = num::cast(t).unwrap();
@ -362,7 +359,6 @@ impl ElipticCurve {
return Ok(h); return Ok(h);
} }
for bit in t_bits { for bit in t_bits {
dbg!(&index);
if index == l { if index == l {
if self.verbose { if self.verbose {
println!("h_{index} = {h}") 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<Self> {
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<ElipticCurvePoint> {
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<ElipticCurvePoint> {
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<ElipticCurvePoint> {
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<String> {
Ok(format!("{}", self))
}
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{}", self))
}
}
impl std::fmt::Display for ElipticCurve{ impl std::fmt::Display for ElipticCurve{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "F(X, Y) = Y² - X³ -{}X - {}", self.a, self.b) write!(f, "F(X, Y) = Y² - X³ -{}X - {}", self.a, self.b)
} }
} }
#[pyclass]
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
/// represent a specific eliptic curves point /// represent a specific eliptic curves point
/// ///
@ -404,21 +473,27 @@ pub struct ElipticCurvePoint {
r: u128, r: u128,
s: u128, s: u128,
is_infinity_point: bool, is_infinity_point: bool,
field: GalloisField,
verbose: bool
} }
#[pymethods]
impl ElipticCurvePoint { impl ElipticCurvePoint {
#[new]
/// create a new point /// 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 { ElipticCurvePoint {
r, r,
s, s,
is_infinity_point: false, is_infinity_point: false,
field,
verbose
} }
} }
fn __str__(&self) -> PyResult<String> {
Ok(format!("{}", self))
}
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{}", self))
}
} }
impl std::fmt::Display for ElipticCurvePoint { 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"); let ec = ElipticCurve::new(f, -3, 3, true).expect("ec cant be created");
// real points // real points
let p = vec![ let p = vec![
ElipticCurvePoint::new(0, 4, f, false), ec.new_point(0, 4 ).unwrap(),
ElipticCurvePoint::new(0, 9, f, false), ec.new_point(0, 9 ).unwrap(),
ElipticCurvePoint::new(1, 1, f, false), ec.new_point(1, 1 ).unwrap(),
ElipticCurvePoint::new(1, 12, f, false), ec.new_point(1, 1 ).unwrap(),
ElipticCurvePoint::new(4, 4, f, false), ec.new_point(4, 4 ).unwrap(),
ElipticCurvePoint::new(4, 9, f, false), ec.new_point(4, 9 ).unwrap(),
ElipticCurvePoint::new(5, 3, f, false), ec.new_point(5, 3 ).unwrap(),
ElipticCurvePoint::new(5, 10, f, false), ec.new_point(5, 10 ).unwrap(),
ElipticCurvePoint::new(7, 0, f, false), ec.new_point(7, 0 ).unwrap(),
ElipticCurvePoint::new(8, 6, f, false), ec.new_point(8, 6 ).unwrap(),
ElipticCurvePoint::new(9, 4, f, false), ec.new_point(9, 4 ).unwrap(),
ElipticCurvePoint::new(9, 9, f, false), ec.new_point(9, 9 ).unwrap(),
ElipticCurvePoint::new(11, 1, f, false), ec.new_point(11, 1 ).unwrap(),
ElipticCurvePoint::new(11, 12, f, false), ec.new_point(11, 12 ).unwrap(),
]; ];
// random values, not part of the e, fc. // random values, not part of the e, fc.
let np = vec![ let np = vec![
ElipticCurvePoint::new(0, 5, f, false), ec.new_point(0, 5).unwrap_err(),
ElipticCurvePoint::new(1, 9, f, false), ec.new_point(1, 9).unwrap_err(),
ElipticCurvePoint::new(1, 4, f, false), 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] #[test]

View File

@ -15,12 +15,12 @@
/// License: MIT /// License: MIT
/// Source: <https://git.cscherr.de/PlexSheep/plexcryptool/> /// Source: <https://git.cscherr.de/PlexSheep/plexcryptool/>
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 core::fmt;
use std::fmt::Debug; use std::fmt::Debug;
use num::{Integer, NumCast, Signed, Unsigned}; use num::{Integer, NumCast};
use pyo3::{prelude::*, exceptions::PyValueError}; use pyo3::{prelude::*, exceptions::PyValueError};
@ -391,6 +391,7 @@ impl GalloisField {
self.cha = i; self.cha = i;
return i; return i;
} }
} }
#[pymethods] #[pymethods]
@ -458,6 +459,20 @@ impl GalloisField {
} }
panic!("No order was found, but n is not 0 and all possibilities have been tried"); panic!("No order was found, but n is not 0 and all possibilities have been tried");
} }
fn __str__(&self) -> PyResult<String> {
Ok(format!("{}", self))
}
fn __repr__(&self) -> PyResult<String> {
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); assert_eq!(field.reduce::<_, u128>(i as u128), i);
} }
let field = GalloisField::new(16, true, None); let _ = GalloisField::new(16, true, None);
} }
#[test] #[test]