From 59a7e22e708d04553c523f7cc95e4949c9845b81 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Fri, 9 Jun 2023 12:36:03 +0200 Subject: [PATCH] subtraction and calculating char in GF --- src/math/ecc.rs | 260 +++++++++++++++++++++----------------------- src/math/gallois.rs | 99 ++++++++++++++--- 2 files changed, 209 insertions(+), 150 deletions(-) diff --git a/src/math/ecc.rs b/src/math/ecc.rs index fc35c89..f67ef82 100644 --- a/src/math/ecc.rs +++ b/src/math/ecc.rs @@ -165,158 +165,146 @@ impl ElipticCurve { if !self.check_point(p2, false) { return Err(String::from("{p2} is not a valid point")); } - 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, - // ); - //} - // case 1: both infty - if p1.is_infinity_point && p2.is_infinity_point { - if self.verbose { - println!("case 1"); - } - return Ok(self.INFINITY_POINT); + // case 1: both infty + if p1.is_infinity_point && p2.is_infinity_point { + if self.verbose { + println!("case 1"); } - // case 2: one is infty - else if p1.is_infinity_point && !p2.is_infinity_point || - !p1.is_infinity_point && p2.is_infinity_point - { - if self.verbose { - println!("case 2"); - } - return Ok(self.INFINITY_POINT); + return Ok(self.INFINITY_POINT); + } + // case 2: one is infty + else if p1.is_infinity_point && !p2.is_infinity_point || + !p1.is_infinity_point && p2.is_infinity_point + { + if self.verbose { + println!("case 2"); } - // case 3: r_1 != r_2 - else if p1.r != p2.r { - if self.verbose { - println!("case 3"); - } - if self.field.prime_base { - let m: u128 = self.field.reduce::(p2.s as i128 - p1.s as i128) * - self.field.inverse( - self.field.reduce::(p2.r as i128 - p1.r as i128) - ).expect("could not find inverse"); - 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, 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, self.field.reduce::<_, u128>(r3)); - } - let r3 = self.field.reduce::<_, u128>(r3); - - let s3 = m.pow(3) - 2*m*p1.r as i128 - m*p2.r as i128 + p1.s as i128; - 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 = 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 = self.new_point(r3, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist"); - - if self.verbose { - seperator(); - println!("result: ({}, {})", p3.r, p3.s); - seperator(); - } - return Ok(p3); - } - else { - panic!("TODO"); - } + return Ok(self.INFINITY_POINT); + } + // case 3: r_1 != r_2 + else if p1.r != p2.r { + if self.verbose { + println!("case 3"); } - // case 4: r_1 = r_2 && s_1 = -s_2 - else if p1.r == p2.r && p1.s == self.neg(p2).s { + if self.field.prime_base { + let m: u128 = self.field.reduce::(p2.s as i128 - p1.s as i128) * + self.field.inverse( + self.field.reduce::(p2.r as i128 - p1.r as i128) + ).expect("could not find inverse"); + let m: i128 = m as i128; if self.verbose { - println!("case 4"); + println!("m = [s_2 - s_1]/[r_2 - r_1] = [{} - {}]/[{} - {}] = {} = {}", + p2.s, p1.s, p2.r, p1.r, m, self.field.reduce::<_, u128>(m)) } - return Ok(self.INFINITY_POINT); - } - // case 5: P + P where P = (r, 0) - else if p1 == p2 && p1.s == 0 { + let m: i128 = self.field.reduce(m); + + let r3 = m.pow(2) - p1.r as i128 - p2.r as i128; if self.verbose { - println!("case 5"); + println!("r_3 = m² - r_1 - r_2 = {} - {} - {} = {} = {}", + m.pow(2), p1.r, p2.r, r3, self.field.reduce::<_, u128>(r3)); } - return Ok(self.INFINITY_POINT); - } - // case 6: P + P where s != 0 - else if p1 == p2 && p1.s != 0 { + let r3 = self.field.reduce::<_, u128>(r3); + + let s3 = m.pow(3) - 2*m*p1.r as i128 - m*p2.r as i128 + p1.s as i128; if self.verbose { - println!("case 6"); + 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)); } - if self.field.prime_base { - let m: i128 = (self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a) * - self.field.inverse( - self.field.reduce::(2 * p1.s) - ).expect("could not find inverse")) as i128; - if self.verbose { - println!("m = [3*r² + a]/[2s] = [3*{}² + {}]/[2*{}] = \ - {}/{} = \ - {}*{} = \ - {} = {}", - p1.r, self.a, p1.s, - - self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a), - 2 * p1.s, - - self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a), - self.field.inverse(self.field.reduce::(2 * p1.s)).unwrap(), - - m, - self.field.reduce::<_, u128>(m) - ); - } - let m: i128 = self.field.reduce(m); - - 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, 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 { - 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 = self.new_point(r3 as u128, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist in curve"); - - if self.verbose { - seperator(); - println!("result: ({}, {})", p3.r, p3.s); - seperator(); - } - return Ok(p3); + 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); } - else { - panic!("TODO"); + let p3 = self.new_point(r3, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist"); + + if self.verbose { + seperator(); + println!("result: ({}, {})", p3.r, p3.s); + seperator(); } + return Ok(p3); } - - // how do we get here? - // this should never occur else { - panic!("No rules for adding these two points, mathmatically impossible.") + panic!("TODO"); } } + // case 4: r_1 = r_2 && s_1 = -s_2 + else if p1.r == p2.r && p1.s == self.neg(p2).s { + if self.verbose { + println!("case 4"); + } + return Ok(self.INFINITY_POINT); + } + // case 5: P + P where P = (r, 0) + else if p1 == p2 && p1.s == 0 { + if self.verbose { + println!("case 5"); + } + return Ok(self.INFINITY_POINT); + } + // case 6: P + P where s != 0 + else if p1 == p2 && p1.s != 0 { + if self.verbose { + println!("case 6"); + } + if self.field.prime_base { + let m: i128 = (self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a) * + self.field.inverse( + self.field.reduce::(2 * p1.s) + ).expect("could not find inverse")) as i128; + if self.verbose { + println!("m = [3*r² + a]/[2s] = [3*{}² + {}]/[2*{}] = \ + {}/{} = \ + {}*{} = \ + {} = {}", + p1.r, self.a, p1.s, + + self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a), + 2 * p1.s, + + self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a), + self.field.inverse(self.field.reduce::(2 * p1.s)).unwrap(), + + m, + self.field.reduce::<_, u128>(m) + ); + } + let m: i128 = self.field.reduce(m); + + 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, 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 { + 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 = self.new_point(r3 as u128, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist in curve"); + + if self.verbose { + seperator(); + println!("result: ({}, {})", p3.r, p3.s); + seperator(); + } + return Ok(p3); + } + else { + panic!("TODO"); + } + } + + // how do we get here? + // this should never occur else { - return Err(String::from("Only prime fields are supported currently")); + panic!("No rules for adding these two points, mathmatically impossible.") } } diff --git a/src/math/gallois.rs b/src/math/gallois.rs index 02be2ba..e5de2f5 100644 --- a/src/math/gallois.rs +++ b/src/math/gallois.rs @@ -18,7 +18,7 @@ use crate::{math::modexp, cplex::printing::seperator, math::modred::modred}; use core::fmt; -use std::{fmt::Debug, ops::BitXor}; +use std::fmt::Debug; use num::{Integer, NumCast}; @@ -205,7 +205,41 @@ impl GalloisField { } else { r = a ^ b; - println!("r = a ^ b = {a:b} ^ {b:b} = {r:b}"); + println!("r = a ^ b = {a:b} ^ {b:b} = {r:b}\n\ + r = a + b = ({}) + ({}) = {}", + self.display(a), + self.display(b), + self.display(r), + ); + } + num::cast(self.reduce::<_, T>(r)).unwrap() + } + + /// subtraction in the field + /// + /// in case of a prime base, addition works as normal, + /// if the base is a prime power, all elements are treated as polynomials, so the + /// operations are changed too. + pub fn sub(&self, a: T, b: T) -> T + where + T: Integer, + T: Debug, + T: NumCast + { + let a: i128 = self.reduce(num::cast::<_, u128>(a).unwrap()); + let b: i128 = self.reduce(num::cast::<_, u128>(b).unwrap()); + let r: i128; + if self.prime_base { + r = a - b; + } + else { + r = a ^ b; + println!("r = a ^ b = {a:b} ^ {b:b} = {r:b}\n\ + r = a + b = ({}) + ({}) = {}", + self.display(a), + self.display(b), + self.display(r), + ); } num::cast(self.reduce::<_, T>(r)).unwrap() } @@ -405,18 +439,30 @@ impl GalloisField { seperator(); println!("calculating characteristic of F_{}", self.base); } - let mut i = 1u128; - while self.reduce::<_, u128>(i) != 0 { - i = self.add(i, 1); - } - if self.verbose { - println!("{i} = {} (mod {})", self.reduce::<_, u128>(i), self.base); - println!("Therefore, char(F_{}) = {i}", self.base); - seperator(); - } + if self.prime_base { + let mut i = 1u128; + while self.reduce::<_, u128>(i) != 0 { + i += 1; + } + if self.verbose { + println!("{i} = {} (mod {})", self.reduce::<_, u128>(i), self.base); + println!("Therefore, char(F_{}) = {i}", self.base); + seperator(); + } - self.cha = i; - return i; + self.cha = i; + return i; + } + else { + if self.base.is_power_of_two() { + // if you need the k part of 2**k = self.base + //let l: u32 = self.base.ilog2(); + return 2; + } + else { + panic!("GalloisField for bases other then primes or powers of two not implemented.") + } + } } /// display an element in the field @@ -428,7 +474,7 @@ impl GalloisField { T: NumCast, T: Debug { - let mut n: u128 = self.reduce(num::cast::<_, u128>(n).unwrap()); + let n: u128 = self.reduce(num::cast::<_, u128>(n).unwrap()); let mut buf: String = String::new(); let n_len = n.count_ones() + n.count_zeros(); let mut first: bool = true; @@ -597,6 +643,31 @@ pub mod test { assert_eq!(field.add(0b1010101, 0b10101010), field.reduce(0b11111111)); } + #[test] + fn test_gallois_sub() { + let field = GalloisField::new(977, true, None); + let ns = [132,1232,121,424]; + for i in 0..976 { + for n in ns { + assert_eq!(field.sub(i, n), field.reduce(i-n)); + } + } + + let field = GalloisField::new(8, true, None); + assert_eq!(field.sub(0b1, 0b10), field.reduce(0b11)); + assert_eq!(field.sub(0b11, 0b10), field.reduce(0b01)); + assert_eq!(field.sub(0b101, 0b1010), field.reduce(0b1111)); + assert_eq!(field.sub(0b1010101, 0b10101010), field.reduce(0b11111111)); + + let field = GalloisField::new(16, true, None); + assert_eq!(field.sub(0b1, 0b10), field.reduce(0b11)); + assert_eq!(field.sub(0b11, 0b10), field.reduce(0b01)); + assert_eq!(field.sub(0b1111, 0b1011), field.reduce(0b0100)); + assert_eq!(field.sub(0b101, 0b1010), field.reduce(0b1111)); + assert_eq!(field.sub(0b1000, 0b111), field.reduce(0b1111)); + assert_eq!(field.sub(0b1010101, 0b10101010), field.reduce(0b11111111)); + } + #[test] fn test_gallois_reduce_c2() { let field = GalloisField::new(16, true, None);