Skip to content

Commit

Permalink
fix: add same point
Browse files Browse the repository at this point in the history
  • Loading branch information
Elvis339 committed Aug 29, 2023
1 parent 812ce0a commit 857f368
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 24 deletions.
11 changes: 10 additions & 1 deletion src/ecc/field_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ impl FieldElement {

Ok((num, prime))
}

pub fn construct_from(num: BigInt, prime: BigInt) -> Result<FieldElement, String> {
if num >= prime || num < BigInt::from(0) {
return Err(format!("Num {} not in field range 0 to {}", num, prime - 1));
}
Ok(Self { num, prime })
}
}

impl fmt::Display for FieldElement {
Expand Down Expand Up @@ -237,7 +244,9 @@ mod tests {

// Verify: x^3 + 7 = (13^3 + 7) % 103 = 79
assert_eq!(
x.pow_mod(BigInt::from(3)).add(new_fe(7, prime.clone())).unwrap(),
x.pow_mod(BigInt::from(3))
.add(new_fe(7, prime.clone()))
.unwrap(),
new_fe(79, prime)
)
}
Expand Down
1 change: 1 addition & 0 deletions src/ecc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
mod field_element;
mod point;
mod scalar;
58 changes: 35 additions & 23 deletions src/ecc/point.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::ecc::field_element::FieldElement;
use crate::ecc::scalar::Scalar;
use num_bigint::BigInt;
use std::fmt::{Display, Formatter};
use std::ops::{Add, Div, Mul, Sub};

#[derive(Debug, Clone)]
pub struct Point {
a: FieldElement,
b: FieldElement,
pub a: FieldElement,
pub b: FieldElement,
x: Option<FieldElement>,
y: Option<FieldElement>,
}
Expand Down Expand Up @@ -94,8 +95,6 @@ impl Add for Point {
));
}

let (_, prime) = self.a.clone().convert::<i64>()?;

// Self is point at infinity
if self.x.is_none() {
return Ok(other);
Expand Down Expand Up @@ -160,35 +159,25 @@ impl Add for Point {
let x1 = self.x.clone().expect("x1 is None");
let y1 = self.y.clone().expect("y1 is None");

if prime < 3 {
return Err(format!("Prime {} too low!", prime));
}

let two = FieldElement::new(2, prime.clone())?;
let three = FieldElement::new(3, prime.clone())?;

// (3 * x1^2 + a)
let quotient = three
.mul(x1.clone().pow_mod(BigInt::from(2)))?
.add(self.a.clone())?;
// 3 * x1^2 + a
let quotient =
Scalar::new(3).mul(x1.clone().pow_mod(BigInt::from(2)).add(self.a.clone())?)?;
// 2 * y1
let dividend = Scalar::new(2).mul(y1.clone())?;

// (2 * y1)
let divident = two.clone().mul(y1.clone())?;

// s = (3 * x1^2 + a) / (2 * y1)
let s = quotient.div(divident)?;
// (3 * x1^2 + a) / (2 * y1)
let s = quotient.div(dividend)?;

// x3 = s^2 - 2 * x1
let x3 = s
.clone()
.pow_mod(BigInt::from(2))
.sub(two)?
.mul(x1.clone())?;
.sub(Scalar::new(2).mul(x1.clone())?)?;

// y3 = s * (x1 - x3) - y1
let y3 = s.mul(x1.sub(x3.clone())?)?.sub(y1)?;

return Point::new(self.a, self.b, Some(x3), Some(y3));
return Point::new(self.a, self.b, Some(x3.clone()), Some(y3));
}

return Err(format!("Invalid"));
Expand Down Expand Up @@ -262,4 +251,27 @@ mod tests {
);
}
}

#[test]
fn add_same_point() {
let prime = 223;
let a = new_fe(0, prime.clone());
let b = new_fe(7, prime.clone());
let x = new_fe(47, prime.clone());
let y = new_fe(71, prime.clone());
let p = Point::new(a.clone(), b.clone(), Some(x), Some(y)).unwrap();

let result = (p.clone() + p.clone()).unwrap();

assert_eq!(
result,
Point::new(
a.clone(),
b.clone(),
Some(new_fe(36, prime.clone())),
Some(new_fe(111, prime.clone()))
)
.unwrap()
)
}
}
49 changes: 49 additions & 0 deletions src/ecc/scalar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::ecc::field_element::FieldElement;
use std::ops::Mul;

#[derive(Debug, Clone)]
pub struct Scalar {
value: i64,
}

impl Scalar {
pub fn new(value: i64) -> Self {
Self { value }
}
}

impl Mul<FieldElement> for Scalar {
type Output = Result<FieldElement, String>;

// Naive impl
fn mul(self, rhs: FieldElement) -> Self::Output {
let prime = rhs.get_prime().clone();
let num = rhs.get_num().clone();
let mut result = FieldElement::construct_from(num.clone(), prime.clone()).unwrap();

let end = self.value;

for _ in 1..end {
result = (result + rhs.clone())?
}

Ok(result)
}
}

#[cfg(test)]
mod tests {
use crate::ecc::field_element::FieldElement;
use crate::ecc::scalar::Scalar;

fn new_fe(num: i64, prime: i64) -> FieldElement {
FieldElement::new(num, prime).unwrap()
}

#[test]
fn multiply_field_element() {
let fe = new_fe(15, 223);
let res = Scalar::new(2) * fe;
assert_eq!(res.unwrap(), new_fe(30, 223))
}
}

0 comments on commit 857f368

Please sign in to comment.