subtraction and calculating char in GF

This commit is contained in:
Christoph J. Scherr 2023-06-09 12:36:03 +02:00
parent 9f3e8718b8
commit 59a7e22e70
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
2 changed files with 209 additions and 150 deletions

View File

@ -165,158 +165,146 @@ impl ElipticCurve {
if !self.check_point(p2, false) { 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 self.field.prime_base { // case 1: both infty
// verbisity stuff if p1.is_infinity_point && p2.is_infinity_point {
//if self.verbose { if self.verbose {
// println!("{} = {}; {} = -{} = {} <=> {}", println!("case 1");
// 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 2: one is infty return Ok(self.INFINITY_POINT);
else if p1.is_infinity_point && !p2.is_infinity_point || }
!p1.is_infinity_point && p2.is_infinity_point // case 2: one is infty
{ else if p1.is_infinity_point && !p2.is_infinity_point ||
if self.verbose { !p1.is_infinity_point && p2.is_infinity_point
println!("case 2"); {
} if self.verbose {
return Ok(self.INFINITY_POINT); println!("case 2");
} }
// case 3: r_1 != r_2 return Ok(self.INFINITY_POINT);
else if p1.r != p2.r { }
if self.verbose { // case 3: r_1 != r_2
println!("case 3"); else if p1.r != p2.r {
} if self.verbose {
if self.field.prime_base { println!("case 3");
let m: u128 = self.field.reduce::<i128, u128>(p2.s as i128 - p1.s as i128) *
self.field.inverse(
self.field.reduce::<i128, u128>(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");
}
} }
// case 4: r_1 = r_2 && s_1 = -s_2 if self.field.prime_base {
else if p1.r == p2.r && p1.s == self.neg(p2).s { let m: u128 = self.field.reduce::<i128, u128>(p2.s as i128 - p1.s as i128) *
self.field.inverse(
self.field.reduce::<i128, u128>(p2.r as i128 - p1.r as i128)
).expect("could not find inverse");
let m: i128 = m as i128;
if self.verbose { 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); let m: i128 = self.field.reduce(m);
}
// case 5: P + P where P = (r, 0) let r3 = m.pow(2) - p1.r as i128 - p2.r as i128;
else if p1 == p2 && p1.s == 0 {
if self.verbose { 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); let r3 = self.field.reduce::<_, u128>(r3);
}
// case 6: P + P where s != 0 let s3 = m.pow(3) - 2*m*p1.r as i128 - m*p2.r as i128 + p1.s as i128;
else if p1 == p2 && p1.s != 0 {
if self.verbose { 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 s3 = self.field.reduce::<_, u128>(s3) as i128;
let m: i128 = (self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a) * if self.verbose {
self.field.inverse( println!("-s_3 = - {s3} = {}", self.field.reduce::<_, u128>(-s3));
self.field.reduce::<u128, u128>(2 * p1.s) println!("Q = ({}, {})", r3, s3);
).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::<u128, u128>(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 { let p3 = self.new_point(r3, self.field.reduce::<_, u128>(-s3)).expect("calculated point does not exist");
panic!("TODO");
if self.verbose {
seperator();
println!("result: ({}, {})", p3.r, p3.s);
seperator();
} }
return Ok(p3);
} }
// how do we get here?
// this should never occur
else { 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::<u128, u128>(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::<u128, u128>(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 { else {
return Err(String::from("Only prime fields are supported currently")); panic!("No rules for adding these two points, mathmatically impossible.")
} }
} }

View File

@ -18,7 +18,7 @@
use crate::{math::modexp, 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, ops::BitXor}; use std::fmt::Debug;
use num::{Integer, NumCast}; use num::{Integer, NumCast};
@ -205,7 +205,41 @@ impl GalloisField {
} }
else { else {
r = a ^ b; 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<T>(&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() num::cast(self.reduce::<_, T>(r)).unwrap()
} }
@ -405,18 +439,30 @@ impl GalloisField {
seperator(); seperator();
println!("calculating characteristic of F_{}", self.base); println!("calculating characteristic of F_{}", self.base);
} }
let mut i = 1u128; if self.prime_base {
while self.reduce::<_, u128>(i) != 0 { let mut i = 1u128;
i = self.add(i, 1); while self.reduce::<_, u128>(i) != 0 {
} i += 1;
if self.verbose { }
println!("{i} = {} (mod {})", self.reduce::<_, u128>(i), self.base); if self.verbose {
println!("Therefore, char(F_{}) = {i}", self.base); println!("{i} = {} (mod {})", self.reduce::<_, u128>(i), self.base);
seperator(); println!("Therefore, char(F_{}) = {i}", self.base);
} seperator();
}
self.cha = i; self.cha = i;
return 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 /// display an element in the field
@ -428,7 +474,7 @@ impl GalloisField {
T: NumCast, T: NumCast,
T: Debug 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 mut buf: String = String::new();
let n_len = n.count_ones() + n.count_zeros(); let n_len = n.count_ones() + n.count_zeros();
let mut first: bool = true; let mut first: bool = true;
@ -597,6 +643,31 @@ pub mod test {
assert_eq!(field.add(0b1010101, 0b10101010), field.reduce(0b11111111)); 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] #[test]
fn test_gallois_reduce_c2() { fn test_gallois_reduce_c2() {
let field = GalloisField::new(16, true, None); let field = GalloisField::new(16, true, None);