ecc point checker, generic reducing in gallois
This commit is contained in:
parent
1246d84267
commit
9d2a972cc9
|
@ -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) => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue