ecc point checker, generic reducing in gallois

This commit is contained in:
Christoph J. Scherr 2023-05-28 11:51:07 +02:00
parent 1246d84267
commit 9d2a972cc9
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
3 changed files with 99 additions and 23 deletions

View File

@ -68,7 +68,7 @@ pub fn main() {
cplex::printing::proc_result_tup_num(result, args); cplex::printing::proc_result_tup_num(result, args);
} }
GalloisActions::Reduce(gal_red_args) => { GalloisActions::Reduce(gal_red_args) => {
let result = field.reduce_neg(gal_red_args.n); let result = field.reduce(gal_red_args.n);
cplex::printing::proc_num(result, args); cplex::printing::proc_num(result, args);
} }
GalloisActions::Invert(gal_inv_args) => { GalloisActions::Invert(gal_inv_args) => {

View File

@ -46,10 +46,53 @@ impl ElipticCurve {
}; };
return e; 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;
}
pub fn check_point(self, p: ElipticCurvePoint) -> bool {
let mut valid = true;
let r = self.f.reduce(self.poly(p.x, p.y));
if self.verbose {
println!("F({}, {}) = {}² - {}³ - {} * {} - {} = {r}",
p.x, p.y, p.y, p.x, self.a, p.x, self.b
)
}
valid &= r == 0;
return valid;
}
}
#[test]
fn test_check_point() {
let f = GalloisField::new(1151, true);
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),
];
// random values, not part of the ec.
let np = vec![
ElipticCurvePoint::new(198, 331),
ElipticCurvePoint::new(100, 927),
ElipticCurvePoint::new(446, 876),
];
for i in p {
dbg!(&i);
assert!(ec.clone().check_point(i));
}
for i in np {
dbg!(&i);
assert!(!ec.clone().check_point(i));
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
#[pyclass] #[pyclass]
/// represent a specific eliptic curves point /// represent a specific eliptic curves point
pub struct ElipticCurvePoint { pub struct ElipticCurvePoint {
@ -60,12 +103,12 @@ pub struct ElipticCurvePoint {
} }
impl ElipticCurvePoint { impl ElipticCurvePoint {
pub fn new(x: i128, y: i128, verbose: bool) -> Self { pub fn new(x: i128, y: i128) -> Self {
ElipticCurvePoint { ElipticCurvePoint {
x, x,
y, y,
is_infinity_point: false, is_infinity_point: false,
verbose verbose: false
} }
} }
@ -79,6 +122,12 @@ impl ElipticCurvePoint {
panic!("TODO"); panic!("TODO");
} }
/// get negative of a point
pub fn neg(p: Self) -> Self {
// TODO
panic!("TODO");
}
/// multiply a point by an integer /// multiply a point by an integer
pub fn mul(n: u128, a: Self) -> Self { pub fn mul(n: u128, a: Self) -> Self {
// TODO // TODO

View File

@ -7,7 +7,9 @@
/// It does also not even come close to statisfying the characteristic of prime powers q = p^k.as /// It does also not even come close to statisfying the characteristic of prime powers q = p^k.as
/// base => p = 0 /// base => p = 0
/// ///
/// Something is wrong here. /// GalloisFields with a base that is a prime power have p^k elements, but only p real elements,
/// the rest are denoted as polynomials with alpha, this makes computation much more complicated.
/// Therefore, currently, I can only support gallois fields with primes as base.
/// ///
/// Author: Christoph J. Scherr <software@cscherr.de> /// Author: Christoph J. Scherr <software@cscherr.de>
/// License: MIT /// License: MIT
@ -16,12 +18,13 @@
use crate::{math::modexp, cplex::printing::seperator}; use crate::{math::modexp, cplex::printing::seperator};
use core::fmt; use core::fmt;
use std::{fmt::Debug, ops::{AddAssign, Add}};
use num::Integer; use num::Integer;
use pyo3::{prelude::*, exceptions::PyValueError}; use pyo3::{prelude::*, exceptions::PyValueError};
use primes::{Sieve, PrimeSet, is_prime}; use primes::is_prime;
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Debug)] #[derive(Debug)]
@ -61,17 +64,30 @@ pub struct GalloisField {
base: u128, base: u128,
cha: u128, cha: u128,
verbose: bool, verbose: bool,
prime_base: bool
} }
/// implementations for the gallois field /// implementations for the gallois field
impl GalloisField { impl GalloisField {
/// make a new gallois field /// make a new gallois field
pub fn new(base: u128, verbose: bool) -> Self { pub fn new(base: u128, verbose: bool) -> Self {
let prime_base: bool = is_prime(base as u64);
if !prime_base {
println!("Non prime bases for a field are currently not supported. {} is not a prime.", base);
panic!("Non prime bases for a field are currently not supported.");
}
let mut field = GalloisField{ let mut field = GalloisField{
base, base,
cha: 0, cha: base,
verbose verbose,
prime_base
}; };
if field.prime_base {
field.cha = base;
}
else {
field.calc_char();
}
if verbose { if verbose {
println!("In Gallois Field F_{}", field.base); println!("In Gallois Field F_{}", field.base);
} }
@ -79,13 +95,21 @@ impl GalloisField {
} }
/// reduce a number to fit into the gallois field /// reduce a number to fit into the gallois field
pub fn reduce(self, n: u128) -> u128 { /// only works with u128 as input
/// depreciated
pub fn reduce_pos(self, n: u128) -> u128 {
return n % self.base; return n % self.base;
} }
/// reduce a negative number to fit into the gallois field /// reduce a negative number to fit into the gallois field
pub fn reduce_neg(self, n: i128) -> u128 { ///
let mut n = n; /// utilizes generic types to reduce any integer
pub fn reduce<T>(self, n: T) -> u128
where
T: Integer,
T: num::cast::AsPrimitive<i128>
{
let mut n: i128 = num::cast::AsPrimitive::as_(n);
if n < 0 { if n < 0 {
while n < 0 { while n < 0 {
n += self.base as i128; n += self.base as i128;
@ -181,7 +205,7 @@ impl GalloisField {
let mut b_pm1_2: u128; let mut b_pm1_2: u128;
for b_candidate in 0..self.base { for b_candidate in 0..self.base {
b_pm1_2 = modexp::modular_exponentiation_wrapper(b_candidate, pm1_2, self.base, false); b_pm1_2 = modexp::modular_exponentiation_wrapper(b_candidate, pm1_2, self.base, false);
if self.reduce(b_pm1_2) == self.reduce_neg(-1) { if self.reduce(b_pm1_2) == self.reduce(-1) {
b = Some(b_candidate); b = Some(b_candidate);
if self.verbose { if self.verbose {
println!("b^([p-1]/[2]) = {}^({pm1_2}) = -1 (mod {})", b.unwrap(), self.base); println!("b^([p-1]/[2]) = {}^({pm1_2}) = -1 (mod {})", b.unwrap(), self.base);
@ -309,15 +333,16 @@ impl GalloisField {
if self.verbose { if self.verbose {
seperator(); seperator();
println!("calculating characteristic of F_{}", self.base); println!("calculating characteristic of F_{}", self.base);
seperator();
} }
let mut i = 1u128; let mut i = 1u128;
while self.reduce(i) > 0 { while self.reduce(i) > 0 {
if self.verbose {
println!("{i}.\t {i} = {} (mod {})", self.reduce(i), self.base)
}
i += 1; i += 1;
} }
if self.verbose {
println!("{i} = {} (mod {})", self.reduce(i), self.base);
println!("Therefore, char(F_{}) = {i}", self.base);
seperator();
}
self.cha = i; self.cha = i;
return i; return i;
@ -341,9 +366,9 @@ impl GalloisField {
#[pyo3(name="reduce")] #[pyo3(name="reduce")]
/// reduce any int /// reduce any int
pub fn py_reduce(&self, n: i128) -> u128 { pub fn py_reduce(&self, n: i128) -> u128 {
if n.is_negative() { //if n.is_negative() {
return self.reduce_neg(n); // return self.reduce_neg(n);
} //}
return self.reduce(n as u128); return self.reduce(n as u128);
} }
@ -407,10 +432,12 @@ fn test_gallois_inverse() {
#[test] #[test]
fn test_calc_char() { fn test_calc_char() {
assert_eq!(GalloisField::new(16, true).calc_char(), 2); assert_eq!(GalloisField::new(83, true).calc_char(), 83);
assert_eq!(GalloisField::new(81, true).calc_char(), 81);
assert_eq!(GalloisField::new(1151, true).calc_char(), 1151); assert_eq!(GalloisField::new(1151, true).calc_char(), 1151);
assert_eq!(GalloisField::new(8, true).calc_char(), 2);
assert_eq!(GalloisField::new(2, true).calc_char(), 2); assert_eq!(GalloisField::new(2, true).calc_char(), 2);
assert_eq!(GalloisField::new(60, true).calc_char(), 3);
// only primes are supported right now. TODO
//assert_eq!(GalloisField::new(8, true).calc_char(), 2);
//assert_eq!(GalloisField::new(64, true).calc_char(), 2);
//assert_eq!(GalloisField::new(2u128.pow(64u32), true).calc_char(), 2);
} }