ecc cli interface and half working add
This commit is contained in:
parent
fe25172b77
commit
461a2666d8
|
@ -20,6 +20,7 @@ name = "plexcryptool"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitvec = "1.0.1"
|
||||||
clap = { version = "4.2.7", features = ["derive"]}
|
clap = { version = "4.2.7", features = ["derive"]}
|
||||||
clap-num = "1.0.2"
|
clap-num = "1.0.2"
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
|
|
|
@ -71,11 +71,12 @@ pub enum MathActions {
|
||||||
/// p minus 1 prime test
|
/// p minus 1 prime test
|
||||||
Pm1(PM1Args),
|
Pm1(PM1Args),
|
||||||
/// calculate in a gallois field
|
/// calculate in a gallois field
|
||||||
|
/// includes Eliptic curves
|
||||||
Gallois(GalloisAction),
|
Gallois(GalloisAction),
|
||||||
/// Euklidian Algorithm
|
/// Euklidian Algorithm
|
||||||
Gcd(GcdArgs),
|
Gcd(GcdArgs),
|
||||||
/// factorize a natural number
|
/// factorize a natural number
|
||||||
Factorize(FactorizeArgs)
|
Factorize(FactorizeArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -137,7 +138,9 @@ pub enum GalloisActions {
|
||||||
/// reduce n to the range of the field
|
/// reduce n to the range of the field
|
||||||
Reduce(GalloisReduceArgs),
|
Reduce(GalloisReduceArgs),
|
||||||
/// calculate the (multiplicative) inverse of n
|
/// calculate the (multiplicative) inverse of n
|
||||||
Invert(GalloisInvertArgs),
|
Inverse(GalloisInverseArgs),
|
||||||
|
/// eliptic curves
|
||||||
|
ECC(ECCAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -152,11 +155,62 @@ pub struct GalloisReduceArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct GalloisInvertArgs {
|
pub struct GalloisInverseArgs {
|
||||||
#[clap(value_parser=maybe_hex::<u128>)]
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
pub n: u128,
|
pub n: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct ECCAction {
|
||||||
|
#[clap(allow_hyphen_values=true)] // allow negative inputs like -19
|
||||||
|
pub a: i128,
|
||||||
|
#[clap(allow_hyphen_values=true)] // allow negative inputs like -19
|
||||||
|
pub b: i128,
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub action: ECCActions
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum ECCActions {
|
||||||
|
/// negate a point
|
||||||
|
Neg(ECCNegArgs),
|
||||||
|
/// add a twp poimts
|
||||||
|
Add(ECCAddArgs),
|
||||||
|
/// multiply a point with an integer
|
||||||
|
/// uses double and add
|
||||||
|
Mul(ECCMulArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct ECCNegArgs {
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub r: u128,
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub s: u128,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct ECCMulArgs {
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub r: u128,
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub s: u128,
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub n: u128,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct ECCAddArgs {
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub r1: u128,
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub s1: u128,
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub r2: u128,
|
||||||
|
#[clap(value_parser=maybe_hex::<u128>)]
|
||||||
|
pub s2: u128,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Clone, Debug, PartialEq, Eq)]
|
#[derive(Subcommand, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum BinaryActions {
|
pub enum BinaryActions {
|
||||||
/// bit rotation/circular shifting (only 32bit)
|
/// bit rotation/circular shifting (only 32bit)
|
||||||
|
@ -166,7 +220,6 @@ pub enum BinaryActions {
|
||||||
Xor(XorArgs),
|
Xor(XorArgs),
|
||||||
/// use a pbox
|
/// use a pbox
|
||||||
Pbox(PboxArgs),
|
Pbox(PboxArgs),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
||||||
|
|
|
@ -88,6 +88,18 @@ pub fn proc_num<T>(num: T, args: Cli)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn proc_display<T>(item: T, args: Cli)
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
if args.machine {
|
||||||
|
println!("{}", item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println!("result is {}", item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// process some int tuple
|
/// process some int tuple
|
||||||
pub fn proc_result_tup_num<T, K>(result: Result<(T, T), K>, args: Cli)
|
pub fn proc_result_tup_num<T, K>(result: Result<(T, T), K>, args: Cli)
|
||||||
where
|
where
|
||||||
|
|
53
src/main.rs
53
src/main.rs
|
@ -68,13 +68,62 @@ 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(gal_red_args.n);
|
let result = field.reduce::<_, u128>(gal_red_args.n);
|
||||||
cplex::printing::proc_num(result, args);
|
cplex::printing::proc_num(result, args);
|
||||||
}
|
}
|
||||||
GalloisActions::Invert(gal_inv_args) => {
|
GalloisActions::Inverse(gal_inv_args) => {
|
||||||
let result = field.inverse(gal_inv_args.n);
|
let result = field.inverse(gal_inv_args.n);
|
||||||
cplex::printing::proc_result_num(result, args);
|
cplex::printing::proc_result_num(result, args);
|
||||||
}
|
}
|
||||||
|
GalloisActions::ECC(ecc_args) => {
|
||||||
|
let ec = math::ecc::ElipticCurve::new(field, ecc_args.a, ecc_args.b, args.verbose).expect("Could not create eliptic curve");
|
||||||
|
match ecc_args.action {
|
||||||
|
ECCActions::Neg(ecc_neg_args) => {
|
||||||
|
let p = ec.new_point(ecc_neg_args.r, ecc_neg_args.s);
|
||||||
|
match p {
|
||||||
|
Ok(p) => {
|
||||||
|
let item = ec.neg(p);
|
||||||
|
cplex::printing::proc_display(item, args)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
cplex::printing::proc_err(e, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ECCActions::Mul(ecc_mul_args) => {
|
||||||
|
let p = ec.new_point(ecc_mul_args.r, ecc_mul_args.s);
|
||||||
|
if p.is_err() {
|
||||||
|
cplex::printing::proc_err(p, args);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let item = ec.mul(p.unwrap(), ecc_mul_args.n);
|
||||||
|
if item.is_err() {
|
||||||
|
cplex::printing::proc_err(item.unwrap_err(), args)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cplex::printing::proc_display(item.unwrap(), args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ECCActions::Add(ecc_add_args) => {
|
||||||
|
let p1 = ec.new_point(ecc_add_args.r1, ecc_add_args.s1);
|
||||||
|
let p2 = ec.new_point(ecc_add_args.r2, ecc_add_args.s2);
|
||||||
|
if p1.is_err() || p2.is_err() {
|
||||||
|
cplex::printing::proc_err(p1, args.clone());
|
||||||
|
cplex::printing::proc_err(p2, args);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let item = ec.add(p1.unwrap(), p2.unwrap());
|
||||||
|
if item.is_err() {
|
||||||
|
cplex::printing::proc_err(item.unwrap_err(), args)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cplex::printing::proc_display(item.unwrap(), args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MathActions::Factorize(fac_args) => {
|
MathActions::Factorize(fac_args) => {
|
||||||
|
|
356
src/math/ecc.rs
356
src/math/ecc.rs
|
@ -1,5 +1,5 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use std::{ops::{Mul, Neg}, fmt::Debug, f32::consts::PI};
|
use crate::cplex::printing::seperator;
|
||||||
|
|
||||||
/// eliptic curve cryptograp.s
|
/// eliptic curve cryptograp.s
|
||||||
///
|
///
|
||||||
|
@ -12,7 +12,12 @@ use std::{ops::{Mul, Neg}, fmt::Debug, f32::consts::PI};
|
||||||
|
|
||||||
use super::gallois::GalloisField;
|
use super::gallois::GalloisField;
|
||||||
|
|
||||||
use num::Integer;
|
use std::{ops::{Mul, Neg}, fmt::{Debug, Display}, f32::consts::PI};
|
||||||
|
|
||||||
|
use num::{Integer, Unsigned, NumCast};
|
||||||
|
|
||||||
|
use bitvec::prelude::*;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
@ -31,30 +36,43 @@ pub struct ElipticCurve {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElipticCurve {
|
impl ElipticCurve {
|
||||||
pub fn new(field: GalloisField, a: i128, b: i128, verbose: bool) -> Result<Self, String> {
|
pub fn new<T>(field: GalloisField, a: T, b: T, verbose: bool) -> Result<Self, String>
|
||||||
|
where
|
||||||
|
T: Integer,
|
||||||
|
T: Debug,
|
||||||
|
T: num::cast::AsPrimitive<i128>,
|
||||||
|
{
|
||||||
|
// convert from generics to i128
|
||||||
|
let a: i128 = num::cast::AsPrimitive::as_(a);
|
||||||
|
let b: i128 = num::cast::AsPrimitive::as_(b);
|
||||||
|
|
||||||
// convert numbers to u128 in the fields
|
// reduce a and b if possible
|
||||||
let a = field.reduce(a);
|
let a = field.reduce::<_, u128>(a);
|
||||||
let b = field.reduce(b);
|
let b = field.reduce::<_, u128>(b);
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
println!("On eliptic curve:\n\
|
||||||
|
F(X, Y) = Y² - X³ - {a}X - {b}")
|
||||||
|
}
|
||||||
|
|
||||||
// check diskriminante
|
// check diskriminante
|
||||||
let d = 4*a.pow(3) + 27*b.pow(2);
|
let d = 4*a.pow(3) + 27*b.pow(2);
|
||||||
if field.reduce(d) == 0 {
|
if field.reduce::<_, u128>(d) == 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
println!("4*{a}³ + 27*{b}² = {d} = {} != 0\n\
|
println!("4*{a}³ + 27*{b}² = {d} = {} != 0\n\
|
||||||
Check for Diskriminante not passed", field.reduce(d));
|
Check for Diskriminante not passed", field.reduce::<_, u128>(d));
|
||||||
}
|
}
|
||||||
return Err(String::from("Diskriminante not 0"));
|
return Err(String::from("Diskriminante not 0"));
|
||||||
}
|
}
|
||||||
else if verbose {
|
else if verbose {
|
||||||
println!("4*{a}³ + 27*{b}² = {d} = {} != 0\n\
|
println!("4*{a}³ + 27*{b}² = {d} = {} != 0\n\
|
||||||
Check for Diskriminante passed", field.reduce(d));
|
Check for Diskriminante passed", field.reduce::<_, u128>(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut infty = ElipticCurvePoint::new(0, 0, field, false);
|
let mut infty = ElipticCurvePoint::new(0, 0, field, false);
|
||||||
infty.is_infinity_point = true;
|
infty.is_infinity_point = true;
|
||||||
let infty = infty;
|
let infty = infty;
|
||||||
let mut e = ElipticCurve {
|
let e = ElipticCurve {
|
||||||
field,
|
field,
|
||||||
a,
|
a,
|
||||||
b,
|
b,
|
||||||
|
@ -65,6 +83,22 @@ impl ElipticCurve {
|
||||||
return Ok(e);
|
return Ok(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// build a new point in the EC
|
||||||
|
pub fn new_point(&self, r: u128, s: u128) -> Result<ElipticCurvePoint, String> {
|
||||||
|
let p = ElipticCurvePoint::new(r, s, self.field, self.verbose);
|
||||||
|
if self.verbose {
|
||||||
|
println!("{p}")
|
||||||
|
}
|
||||||
|
match self.check_point(p, self.verbose) {
|
||||||
|
true => {
|
||||||
|
return Ok(p);
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
return Err(String::from("the point you want to create is not on the EC"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// calculate a value for coordinates
|
/// calculate a value for coordinates
|
||||||
pub fn poly<T>(&self, r: T, s: T) -> i128
|
pub fn poly<T>(&self, r: T, s: T) -> i128
|
||||||
where
|
where
|
||||||
|
@ -79,7 +113,7 @@ impl ElipticCurve {
|
||||||
let r: u128 = num::cast::AsPrimitive::as_(r);
|
let r: u128 = num::cast::AsPrimitive::as_(r);
|
||||||
let s: u128 = num::cast::AsPrimitive::as_(s);
|
let s: u128 = num::cast::AsPrimitive::as_(s);
|
||||||
let res = (s.pow(2) as u128) - (r.pow(3) as u128) - (self.a * r) - self.b;
|
let res = (s.pow(2) as u128) - (r.pow(3) as u128) - (self.a * r) - self.b;
|
||||||
let res1 = self.field.reduce(res);
|
let res1 = self.field.reduce::<_, u128>(res);
|
||||||
if self.verbose {
|
if self.verbose {
|
||||||
println!("F({}, {}) = {}² - {}³ - {} * {} - {} = {res} = {res1}",
|
println!("F({}, {}) = {}² - {}³ - {} * {} - {} = {res} = {res1}",
|
||||||
r, s, s, r, self.a, r, self.b
|
r, s, s, r, self.a, r, self.b
|
||||||
|
@ -88,13 +122,13 @@ impl ElipticCurve {
|
||||||
return res1 as i128;
|
return res1 as i128;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_point(self, p: ElipticCurvePoint) -> bool {
|
pub fn check_point(&self, p: ElipticCurvePoint, verbose: bool) -> bool {
|
||||||
let mut valid = true;
|
let mut valid = true;
|
||||||
|
|
||||||
// insert into poly
|
// insert into poly
|
||||||
let left = self.field.reduce(p.s.pow(2));
|
let left = self.field.reduce::<_, u128>(p.s.pow(2));
|
||||||
let right = self.field.reduce((p.r.pow(3) as u128) + self.a*p.r + self.b);
|
let right = self.field.reduce::<_, u128>((p.r.pow(3) as u128) + self.a*p.r + self.b);
|
||||||
if self.verbose {
|
if self.verbose && verbose {
|
||||||
let unred_left = p.s.pow(2);
|
let unred_left = p.s.pow(2);
|
||||||
let unred_right = p.r.pow(3) + self.a*p.r + self.b;
|
let unred_right = p.r.pow(3) + self.a*p.r + self.b;
|
||||||
println!("All Points need to fullfill this equation:\n\
|
println!("All Points need to fullfill this equation:\n\
|
||||||
|
@ -117,68 +151,148 @@ impl ElipticCurve {
|
||||||
|
|
||||||
|
|
||||||
/// add two points
|
/// add two points
|
||||||
pub fn add(&self, p1: ElipticCurvePoint, p2: ElipticCurvePoint) -> Result<ElipticCurvePoint, String> {
|
pub fn add(&self, p1: ElipticCurvePoint, p2: ElipticCurvePoint) ->
|
||||||
|
Result<ElipticCurvePoint, String> {
|
||||||
|
if self.verbose {
|
||||||
|
seperator();
|
||||||
|
println!("adding {p1} + {p2}");
|
||||||
|
seperator();
|
||||||
|
}
|
||||||
if p1.field != p2.field {
|
if p1.field != p2.field {
|
||||||
return Err(String::from("Points are not on the same field"));
|
return Err(String::from("Points are not on the same field"));
|
||||||
}
|
}
|
||||||
|
if !self.check_point(p1, self.verbose) {
|
||||||
|
return Err(String::from("{p1} is not a valid point"));
|
||||||
|
}
|
||||||
|
if !self.check_point(p2, self.verbose) {
|
||||||
|
return Err(String::from("{p2} is not a valid point"));
|
||||||
|
}
|
||||||
if p1.field.prime_base {
|
if p1.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
|
// case 1: both infty
|
||||||
if p1.is_infinity_point && p2.is_infinity_point {
|
if p1.is_infinity_point && p2.is_infinity_point {
|
||||||
|
if self.verbose {
|
||||||
|
println!("case 1");
|
||||||
|
}
|
||||||
return Ok(self.INFINITY_POINT);
|
return Ok(self.INFINITY_POINT);
|
||||||
}
|
}
|
||||||
// case 2: one is infty
|
// case 2: one is infty
|
||||||
else if p1.is_infinity_point && !p2.is_infinity_point {
|
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);
|
||||||
}
|
}
|
||||||
else if !p1.is_infinity_point && p2.is_infinity_point {
|
// case 4: r_1 = r_2 && s_1 = -s_2
|
||||||
return Ok(p1);
|
else if p1.r == p2.r && p1.s == self.neg(p2).s {
|
||||||
|
if self.verbose {
|
||||||
|
println!("case 4");
|
||||||
|
}
|
||||||
|
return Ok(self.INFINITY_POINT);
|
||||||
}
|
}
|
||||||
// case 3: r_1 != r_2
|
// case 3: r_1 != r_2
|
||||||
else if p1.r != p2.r {
|
else if p1.r != p2.r {
|
||||||
if self.field.prime_base {
|
|
||||||
let m = self.field.reduce(p2.s - p1.s) *
|
|
||||||
self.field.inverse(
|
|
||||||
self.field.reduce(p2.r - p1.r)
|
|
||||||
).expect("could not find inverse");
|
|
||||||
if self.verbose || p2.verbose {
|
|
||||||
println!("m = [s_2 - s_1]/[r_2 - r_1] = [{} - {}]/[{} - {}] = {} = {}",
|
|
||||||
p2.s, p1.s, p2.r, p1.r, m, p1.field.reduce(m))
|
|
||||||
}
|
|
||||||
let m = self.field.reduce(m);
|
|
||||||
|
|
||||||
let r3 = self.field.reduce(m.pow(3)) - p1.r - p2.r;
|
|
||||||
if self.verbose {
|
if self.verbose {
|
||||||
println!("r_3 = m³ - r_1 - r_2 = {} - {} - {} = {} = {}",
|
println!("case 3");
|
||||||
m.pow(3), p1.r, p2.r, r3, p1.field.reduce(r3));
|
|
||||||
}
|
}
|
||||||
let r3 = self.field.reduce(r3);
|
if self.field.prime_base {
|
||||||
|
let m: u128 = self.field.reduce::<i128, u128>(p2.s as i128 - p1.s as i128) *
|
||||||
let s3 = m.pow(3) - 2*m*p1.r - m*p2.r + p1.s;
|
self.field.inverse(
|
||||||
if self.verbose || p2.verbose {
|
self.field.reduce::<i128, u128>(p2.r as i128 - p1.r as i128)
|
||||||
println!("s_3 = m³ − 2*m*r_1 − m*r_2 + s1 = {} - 2*{m}*{} - {m}*{} + {} = {} = {}",
|
).expect("could not find inverse");
|
||||||
m.pow(3), p1.r, p2.r, p1.s, s3, self.field.reduce(s3));
|
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, p1.field.reduce::<_, u128>(m))
|
||||||
}
|
}
|
||||||
let s3 = self.field.reduce(s3) as i128;
|
let m: i128 = self.field.reduce(m);
|
||||||
let p = ElipticCurvePoint::new(r3, self.field.reduce(-s3), self.field, self.verbose);
|
|
||||||
|
|
||||||
panic!("TODO");
|
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, p1.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));
|
||||||
|
}
|
||||||
|
let p3 = ElipticCurvePoint::new(r3, self.field.reduce::<_, u128>(-s3),
|
||||||
|
self.field, self.verbose);
|
||||||
|
|
||||||
|
if self.verbose {
|
||||||
|
seperator();
|
||||||
|
println!("result: ({}, {})", p3.r, p3.s);
|
||||||
|
seperator();
|
||||||
|
}
|
||||||
|
return Ok(p3);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
panic!("TODO");
|
panic!("TODO");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// case 4: r_1 = r_2 && s_1 = -s_2
|
|
||||||
else if p1.r == p2.r && p1.s == self.neg(p2).s {
|
|
||||||
return Ok(self.INFINITY_POINT);
|
|
||||||
}
|
|
||||||
// case 5: P + P where P = (r, 0)
|
// case 5: P + P where P = (r, 0)
|
||||||
else if p1 == p2 && p1.s == 0 {
|
else if p1 == p2 && p1.s == 0 {
|
||||||
|
if self.verbose {
|
||||||
|
println!("case 5");
|
||||||
|
}
|
||||||
return Ok(self.INFINITY_POINT);
|
return Ok(self.INFINITY_POINT);
|
||||||
}
|
}
|
||||||
// case 6: P + P where s != 0
|
// case 6: P + P where s != 0
|
||||||
else if p1 == p2 && p1.s != 0 {
|
else if p1 == p2 && p1.s != 0 {
|
||||||
|
if self.verbose {
|
||||||
|
println!("case 6");
|
||||||
|
}
|
||||||
if self.field.prime_base {
|
if self.field.prime_base {
|
||||||
panic!("TODO");
|
let m: i128 = (self.field.reduce::<_, u128>(3 * p1.r.pow(2) + self.a) *
|
||||||
|
self.field.inverse(
|
||||||
|
self.field.reduce::<u128, u128>(2 * p1.r)
|
||||||
|
).expect("could not find inverse")) as i128;
|
||||||
|
if self.verbose {
|
||||||
|
println!("m = [3*r²]/[2s] = [3*{}²]/[2*{}] = {} = {}",
|
||||||
|
p1.r, p1.s, 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, p1.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 || p2.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 = ElipticCurvePoint::new(r3 as u128, self.field.reduce::<_, u128>(-s3),
|
||||||
|
self.field, self.verbose);
|
||||||
|
|
||||||
|
if self.verbose {
|
||||||
|
seperator();
|
||||||
|
println!("result: ({}, {})", p3.r, p3.s);
|
||||||
|
seperator();
|
||||||
|
}
|
||||||
|
return Ok(p3);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
panic!("TODO");
|
panic!("TODO");
|
||||||
|
@ -188,7 +302,7 @@ impl ElipticCurve {
|
||||||
// how do we get here?
|
// how do we get here?
|
||||||
// this should never occur
|
// this should never occur
|
||||||
else {
|
else {
|
||||||
panic!("No rules for adding these two points, should not be possible mathmatically.")
|
panic!("No rules for adding these two points, mathmatically impossible.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -198,18 +312,70 @@ impl ElipticCurve {
|
||||||
|
|
||||||
/// get negative of a point
|
/// get negative of a point
|
||||||
pub fn neg(&self, p: ElipticCurvePoint) -> ElipticCurvePoint {
|
pub fn neg(&self, p: ElipticCurvePoint) -> ElipticCurvePoint {
|
||||||
return ElipticCurvePoint::new(
|
self.new_point(p.r, self.field.reduce::<_, u128>(-(p.s as i128))).expect("negation of \
|
||||||
p.r,
|
point is not on field, math error")
|
||||||
p.field.reduce(-(p.s as i128)),
|
|
||||||
p.field,
|
|
||||||
p.verbose
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// multip.s a point by an integer
|
/// multip.s a point by an integer
|
||||||
pub fn mul(self, p: ElipticCurvePoint, n: u128) -> ElipticCurvePoint {
|
pub fn mul<T>(&self, g: ElipticCurvePoint, t: T) -> Result<ElipticCurvePoint, String>
|
||||||
// TODO
|
where
|
||||||
panic!("TODO");
|
T: Integer,
|
||||||
|
T: NumCast,
|
||||||
|
T: Debug,
|
||||||
|
T: Unsigned,
|
||||||
|
{
|
||||||
|
if !self.check_point(g, self.verbose) {
|
||||||
|
return Err(String::from("invalid point"));
|
||||||
|
}
|
||||||
|
let t: usize = num::cast(t).unwrap();
|
||||||
|
if t < 1 {
|
||||||
|
return Err(String::from("point multiplication works only if t > 0"));
|
||||||
|
}
|
||||||
|
if self.verbose {
|
||||||
|
println!("h = t * g = {t} * {g}\n\
|
||||||
|
t = [{:b}]2", t)
|
||||||
|
}
|
||||||
|
let mut t_bits = BitVec::<_, Msb0>::from_element(t);
|
||||||
|
t_bits.reverse();
|
||||||
|
while t_bits[t_bits.len() - 1] == false {
|
||||||
|
t_bits.pop();
|
||||||
|
}
|
||||||
|
t_bits.reverse();
|
||||||
|
let l = t_bits.len() - 1;
|
||||||
|
let mut lh: ElipticCurvePoint = g;
|
||||||
|
let mut h: ElipticCurvePoint = g;
|
||||||
|
let mut index: usize = l;
|
||||||
|
if l == 0 {
|
||||||
|
return Ok(h);
|
||||||
|
}
|
||||||
|
for bit in t_bits {
|
||||||
|
if index == l {
|
||||||
|
if self.verbose {
|
||||||
|
println!("h_{index} = {h}")
|
||||||
|
}
|
||||||
|
index -= 1;
|
||||||
|
}
|
||||||
|
h = self.add(lh, lh).expect("error while performing point multiplication");
|
||||||
|
if bit == false {
|
||||||
|
h = self.add(h, g).expect("error while performing point multiplication");
|
||||||
|
}
|
||||||
|
// else h = h
|
||||||
|
assert!(self.check_point(h, false));
|
||||||
|
lh = h;
|
||||||
|
if self.verbose {
|
||||||
|
println!("h_{index} = {h}")
|
||||||
|
}
|
||||||
|
index -= 1;
|
||||||
|
}
|
||||||
|
// now we should have reached h_0
|
||||||
|
|
||||||
|
return Ok(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ElipticCurve{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "F(X, Y) = Y² - X³ -{}X - {}", self.a, self.b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +404,17 @@ impl ElipticCurvePoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ElipticCurvePoint {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
if self.is_infinity_point {
|
||||||
|
write!(f, "(∞ INFINITY)")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write!(f, "({}, {})", self.r, self.s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
|
|
||||||
|
@ -278,10 +455,71 @@ pub mod test {
|
||||||
ElipticCurvePoint::new(1, 4, f, false),
|
ElipticCurvePoint::new(1, 4, f, false),
|
||||||
];
|
];
|
||||||
for i in p {
|
for i in p {
|
||||||
assert!(ec.clone().check_point(i));
|
assert!(ec.clone().check_point(i, true));
|
||||||
}
|
}
|
||||||
for i in np {
|
for i in np {
|
||||||
assert!(!ec.clone().check_point(i));
|
assert!(!ec.clone().check_point(i, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_points() {
|
||||||
|
let f = GalloisField::new(11, true, None);
|
||||||
|
let ec = ElipticCurve::new(f, 1, 1, true).expect("ec cant be created");
|
||||||
|
let p1 = ec.new_point(3, 3).expect("point is on ec but an error occurs");
|
||||||
|
let p2 = ec.new_point(6, 5).expect("point is on ec but an error occurs");
|
||||||
|
let p3 = ec.new_point(0, 10).expect("point is on ec but an error occurs");
|
||||||
|
assert_eq!(ec.add(p1, p2).expect("error for possible addition"), p3);
|
||||||
|
|
||||||
|
let f = GalloisField::new(13, true, None);
|
||||||
|
let ec = ElipticCurve::new(f, -3, 3, true).expect("ec cant be created");
|
||||||
|
let p1 = ec.new_point(1, 1).expect("point is on ec but an error occurs");
|
||||||
|
let p2 = ec.new_point(5, 3).expect("point is on ec but an error occurs");
|
||||||
|
let p3 = ec.new_point(4, 4).expect("point is on ec but an error occurs");
|
||||||
|
let p4 = ec.new_point(8, 6).expect("point is on ec but an error occurs");
|
||||||
|
let p5 = ec.new_point(11, 12).expect("point is on ec but an error occurs");
|
||||||
|
assert_eq!(ec.add(p1, p2).expect("error for possible addition"), p3);
|
||||||
|
assert_eq!(ec.add(p2, p4).expect("error for possible addition"), p1);
|
||||||
|
assert_eq!(ec.add(p1, p1).expect("error for possible addition"), p5);
|
||||||
|
|
||||||
|
let f = GalloisField::new(19, true, None);
|
||||||
|
let ec = ElipticCurve::new(f, 7, 13, true).expect("ec cant be created");
|
||||||
|
let p1 = ec.new_point(2, 15).expect("point is on ec but an error occurs");
|
||||||
|
let p2 = ec.new_point(6, 10).expect("point is on ec but an error occurs");
|
||||||
|
let p3 = ec.new_point(9, 8).expect("point is on ec but an error occurs");
|
||||||
|
assert_eq!(ec.add(p1, p2).expect("error for possible addition"), p3);
|
||||||
|
|
||||||
|
let f = GalloisField::new(13, true, None);
|
||||||
|
let ec = ElipticCurve::new(f, 7, 11, true).expect("ec cant be created");
|
||||||
|
let p1 = ec.new_point(4, 5).expect("point is on ec but an error occurs");
|
||||||
|
let p2 = ec.new_point(6, 10).expect("point is on ec but an error occurs");
|
||||||
|
assert_eq!(ec.add(p1, p1).expect("error for possible addition"), p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mul_points() {
|
||||||
|
// from ecc lectures
|
||||||
|
let f = GalloisField::new(13, true, None);
|
||||||
|
let ec = ElipticCurve::new(f, 7, 11, true).expect("ec cant be created");
|
||||||
|
let p1 = ec.new_point(4, 5).expect("point is on ec but an error occurs");
|
||||||
|
let p2 = ec.new_point(6, 10).expect("point is on ec but an error occurs");
|
||||||
|
let p3 = ec.new_point(4, 8).expect("point is on ec but an error occurs");
|
||||||
|
let p4 = ec.new_point(6, 3).expect("point is on ec but an error occurs");
|
||||||
|
assert_eq!(ec.mul(p1, 2u32).expect("error for possible addition"), p2);
|
||||||
|
assert_eq!(ec.mul(p1, 4u32).expect("error for possible addition"), p3);
|
||||||
|
assert_eq!(ec.mul(p3, 2u32).expect("error for possible addition"), p4);
|
||||||
|
assert_eq!(ec.mul(p2, 4u32).expect("error for possible addition"), p4);
|
||||||
|
|
||||||
|
//let f = GalloisField::new(13, true, None);
|
||||||
|
//let ec = ElipticCurve::new(f, -3, 3, true).expect("ec cant be created");
|
||||||
|
//let p1 = ec.new_point(1, 1).expect("point is on ec but an error occurs");
|
||||||
|
//let p2 = ec.new_point(11, 12).expect("point is on ec but an error occurs");
|
||||||
|
//assert_eq!(ec.mul(p1, 2u64).expect("error for possible addition"), p2);
|
||||||
|
|
||||||
|
//let f = GalloisField::new(17, true, None);
|
||||||
|
//let ec = ElipticCurve::new(f, 11, 3, true).expect("ec cant be created");
|
||||||
|
//let p1 = ec.new_point(5, 8).expect("point is on ec but an error occurs");
|
||||||
|
//let p2 = ec.new_point(6, 8).expect("point is on ec but an error occurs");
|
||||||
|
//assert_eq!(ec.mul(p1, 10u128).expect("error for possible addition"), p2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,13 @@ pub const F_256_DEFAULT_RELATION: u128 = 0x11b;
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// used when trying to find a root for a number which does not have a root.
|
/// used when trying to find a root for a number which does not have a root.
|
||||||
pub struct NoInverseError;
|
pub struct NoInverseError {
|
||||||
|
pub n: u128
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for NoInverseError {
|
impl fmt::Display for NoInverseError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "inverse for 0 does not exist")
|
write!(f, "inverse for {} does not exist", self.n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -136,12 +138,10 @@ impl GalloisField {
|
||||||
T: Integer,
|
T: Integer,
|
||||||
T: NumCast,
|
T: NumCast,
|
||||||
T: Debug,
|
T: Debug,
|
||||||
K: Unsigned,
|
|
||||||
K: Integer,
|
K: Integer,
|
||||||
K: NumCast,
|
K: NumCast,
|
||||||
K: Debug,
|
K: Debug,
|
||||||
{
|
{
|
||||||
dbg!(&n);
|
|
||||||
let mut n: i128 = num::cast(n).unwrap();
|
let mut n: i128 = num::cast(n).unwrap();
|
||||||
if self.prime_base {
|
if self.prime_base {
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
|
@ -175,9 +175,8 @@ impl GalloisField {
|
||||||
|
|
||||||
/// find the multiplicative inverse of a number
|
/// find the multiplicative inverse of a number
|
||||||
pub fn inverse(self, n: u128) -> Result<u128, NoInverseError> {
|
pub fn inverse(self, n: u128) -> Result<u128, NoInverseError> {
|
||||||
dbg!(&n);
|
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return Err(NoInverseError);
|
return Err(NoInverseError{n});
|
||||||
}
|
}
|
||||||
let egcd = (n as i128).extended_gcd(&(self.base as i128));
|
let egcd = (n as i128).extended_gcd(&(self.base as i128));
|
||||||
let egcd = self.reduce(egcd.x);
|
let egcd = self.reduce(egcd.x);
|
||||||
|
@ -462,26 +461,32 @@ impl GalloisField {
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#[test]
|
|
||||||
fn test_gallois_sqrt() {
|
#[cfg(test)]
|
||||||
|
pub mod test {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gallois_sqrt() {
|
||||||
let field = GalloisField::new(977, true, None);
|
let field = GalloisField::new(977, true, None);
|
||||||
assert_eq!(field.sqrt(269).expect("function says there is no root but there is"), (313, 664));
|
assert_eq!(field.sqrt(269).expect("function says there is no root but there is"), (313, 664));
|
||||||
assert_eq!(field.sqrt(524).expect("function says there is no root but there is"), (115, 862));
|
assert_eq!(field.sqrt(524).expect("function says there is no root but there is"), (115, 862));
|
||||||
assert_eq!(field.sqrt(275).expect("function says there is no root but there is"), (585, 392));
|
assert_eq!(field.sqrt(275).expect("function says there is no root but there is"), (585, 392));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gallois_reduce() {
|
fn test_gallois_reduce() {
|
||||||
let field = GalloisField::new(977, true, None);
|
let field = GalloisField::new(977, true, None);
|
||||||
for i in 0..976u128 {
|
for i in 0..976u128 {
|
||||||
assert_eq!(field.reduce::<_, u128>(i as u128), i);
|
assert_eq!(field.reduce::<_, u128>(i as u128), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
let field = GalloisField::new(16, true, None);
|
let field = GalloisField::new(16, true, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gallois_inverse() {
|
fn test_gallois_inverse() {
|
||||||
let field = GalloisField::new(31, true, None);
|
let field = GalloisField::new(31, true, None);
|
||||||
assert_eq!(field.inverse(12).unwrap(), 13);
|
assert_eq!(field.inverse(12).unwrap(), 13);
|
||||||
assert_eq!(field.inverse(28).unwrap(), 10);
|
assert_eq!(field.inverse(28).unwrap(), 10);
|
||||||
|
@ -501,10 +506,10 @@ fn test_gallois_inverse() {
|
||||||
let field = GalloisField::new(16, true, None);
|
let field = GalloisField::new(16, true, None);
|
||||||
assert_eq!(field.inverse(0x130).unwrap(), 0);
|
assert_eq!(field.inverse(0x130).unwrap(), 0);
|
||||||
assert!(field.inverse(0).is_err());
|
assert!(field.inverse(0).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_calc_char() {
|
fn test_calc_char() {
|
||||||
assert_eq!(GalloisField::new(83, true, None).calc_char(), 83);
|
assert_eq!(GalloisField::new(83, true, None).calc_char(), 83);
|
||||||
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);
|
||||||
|
@ -513,4 +518,5 @@ fn test_calc_char() {
|
||||||
//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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue