Compare commits

..

No commits in common. "dbbd466a56acd3b715563e171691738eae03a53d" and "d494db52169b68a4c423f3cba8c3cb016a9247be" have entirely different histories.

2 changed files with 71 additions and 114 deletions

View file

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

View file

@ -66,11 +66,11 @@ impl fmt::Display for NoRootError {
#[pyclass] #[pyclass]
/// represent a gallois field /// represent a gallois field
pub struct GalloisField { pub struct GalloisField {
pub base: u128, base: u128,
pub cha: u128, cha: u128,
pub verbose: bool, verbose: bool,
pub prime_base: bool, prime_base: bool,
pub relation: Option<u128> relation: Option<u128>
} }
/// implementations for the gallois field /// implementations for the gallois field
@ -379,6 +379,19 @@ impl GalloisField {
self.cha = i; self.cha = i;
return i; return i;
} }
/// calculate the order of a element
pub fn calc_ord(self, n: u128) -> Option<u128> {
if n == 0 {
return None;
}
for ord in 2..self.base {
if self.pow(n, ord) == 1 {
return Some(ord);
}
}
panic!("No order was found, but n is not 0 and all possibilities have been tried");
}
} }
#[pymethods] #[pymethods]
@ -433,19 +446,6 @@ impl GalloisField {
} }
} }
} }
/// calculate the order of a element
pub fn calc_ord(&self, n: u128) -> Option<u128> {
if n == 0 {
return None;
}
for ord in 2..self.base {
if self.pow(n, ord) == 1 {
return Some(ord);
}
}
panic!("No order was found, but n is not 0 and all possibilities have been tried");
}
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -496,8 +496,8 @@ fn test_calc_char() {
assert_eq!(GalloisField::new(1151, true, None).calc_char(), 1151); assert_eq!(GalloisField::new(1151, true, None).calc_char(), 1151);
assert_eq!(GalloisField::new(2, true, None).calc_char(), 2); assert_eq!(GalloisField::new(2, true, None).calc_char(), 2);
//// experimental // experimental
//assert_eq!(GalloisField::new(8, true, None).calc_char(), 2); assert_eq!(GalloisField::new(8, true, None).calc_char(), 2);
//assert_eq!(GalloisField::new(64, true, None).calc_char(), 2); assert_eq!(GalloisField::new(64, true, None).calc_char(), 2);
////assert_eq!(GalloisField::new(2u128.pow(64u32), true, None).calc_char(), 2); //assert_eq!(GalloisField::new(2u128.pow(64u32), true, None).calc_char(), 2);
} }