Skip to content

Commit

Permalink
Pairing (#5)
Browse files Browse the repository at this point in the history
* update

* update

* Update

* update

* Update

* update
  • Loading branch information
Koukyosyumei authored Dec 20, 2024
1 parent fae24df commit a8196cc
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 304 deletions.
126 changes: 39 additions & 87 deletions myzkp/src/modules/bn128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ use crate::modules::ring::Ring;
use lazy_static::lazy_static;
use num_bigint::BigInt;
use num_bigint::ToBigInt;
use num_traits::FromPrimitive;
use num_traits::{One, Zero};
use paste::paste;
use std::str::FromStr;

use crate::modules::curve::{miller, EllipticCurve, EllipticCurvePoint};
use crate::modules::curve::{get_lambda, miller, EllipticCurve, EllipticCurvePoint};
use crate::modules::efield::{ExtendedFieldElement, IrreduciblePoly};
use crate::modules::field::Field;
use crate::modules::field::{FiniteFieldElement, ModulusValue};
use crate::modules::polynomial::Polynomial;
use crate::{define_myzkp_curve_type, define_myzkp_modulus_type};
Expand All @@ -20,8 +18,8 @@ define_myzkp_modulus_type!(
);
define_myzkp_curve_type!(BN128Curve, "0", "3");

type Fq = FiniteFieldElement<BN128Modulus>;
type G1Point = EllipticCurvePoint<Fq, BN128Curve>;
pub type Fq = FiniteFieldElement<BN128Modulus>;
pub type G1Point = EllipticCurvePoint<Fq, BN128Curve>;

// Define Fq2 as a quadratic extension field
#[derive(Debug, Clone, PartialEq, Hash)]
Expand All @@ -38,8 +36,8 @@ impl IrreduciblePoly<Fq> for Fq2Poly {
&MODULUS_Fq2
}
}
type Fq2 = ExtendedFieldElement<BN128Modulus, Fq2Poly>;
type G2Point = EllipticCurvePoint<Fq2, BN128Curve>;
pub type Fq2 = ExtendedFieldElement<BN128Modulus, Fq2Poly>;
pub type G2Point = EllipticCurvePoint<Fq2, BN128Curve>;

// Define Fq2 as a quadratic extension field
#[derive(Debug, Clone, PartialEq, Hash)]
Expand Down Expand Up @@ -73,7 +71,7 @@ impl IrreduciblePoly<Fq> for Fq12Poly {
type Fq12 = ExtendedFieldElement<BN128Modulus, Fq12Poly>;
type G12Point = EllipticCurvePoint<Fq12, BN128Curve>;

pub fn cast_G1_to_G12(g: G1Point) -> G12Point {
pub fn cast_g1_to_g12(g: G1Point) -> G12Point {
if g.is_point_at_infinity() {
return G12Point::point_at_infinity();
}
Expand All @@ -88,7 +86,7 @@ pub fn cast_G1_to_G12(g: G1Point) -> G12Point {
)
}

pub fn twist_G2_to_G12(g: G2Point) -> G12Point {
pub fn twist_g2_to_g12(g: G2Point) -> G12Point {
if g.is_point_at_infinity() {
return G12Point::point_at_infinity();
}
Expand Down Expand Up @@ -137,82 +135,36 @@ pub fn twist_G2_to_G12(g: G2Point) -> G12Point {
);
}

pub fn linefunc<F: Field, E: EllipticCurve>(
p: &EllipticCurvePoint<F, E>,
q: &EllipticCurvePoint<F, E>,
t: &EllipticCurvePoint<F, E>,
) -> F {
let x1 = p.x.as_ref().unwrap();
let y1 = p.y.as_ref().unwrap();
let x2 = q.x.as_ref().unwrap();
let y2 = q.y.as_ref().unwrap();
let xt = t.x.as_ref().unwrap();
let yt = t.y.as_ref().unwrap();

if x1 != x2 {
let m = (y2.sub_ref(&y1)) / (x2.sub_ref(&x1));
return (m.mul_ref(&xt.sub_ref(&x1))).sub_ref(&yt.sub_ref(&y1));
} else if y1 == y2 {
let m = ((x1.pow(2)).mul_ref(&F::from_value(3))) / (y1.mul_ref(&F::from_value(2)));
return (m.mul_ref(&xt.sub_ref(&x1))).sub_ref(&yt.sub_ref(&y1));
} else {
return xt.sub_ref(x1);
}
}

pub fn vanila_miller<F: Field, E: EllipticCurve>(
p: &EllipticCurvePoint<F, E>,
q: &EllipticCurvePoint<F, E>,
m: &BigInt,
) -> F {
if p == q {
return F::one();
}

let mut r = q.clone();
let mut f = F::one();

let ate_loop_count = BigInt::from_str("29793968203157093288").unwrap();
let log_ate_loop_count = 63;
let field_modulus = BigInt::from_str(
"21888242871839275222246405745257275088696311157297823662689037894645226208583",
)
.unwrap();

for i in (0..=log_ate_loop_count).rev() {
f = f.mul_ref(&f) * linefunc(&r, &r, &p);
r = r.double();
if ate_loop_count.bit(i) {
f = f.mul_ref(&linefunc(&r, &q, &p));
r = r.add_ref(&q);
}
}

// Assert: r == multiply(&q, &ate_loop_count)
pub fn optimal_ate_pairing(p_g1: &G1Point, q_g2: &G2Point) -> Fq12 {
// https://eprint.iacr.org/2010/354.pdf
let p: G12Point = cast_g1_to_g12(p_g1.clone());
let q: G12Point = twist_g2_to_g12(q_g2.clone());
let m = BN128Modulus::modulus();

let q1 = EllipticCurvePoint::<F, E>::new(
q.x.clone().unwrap().pow(m.clone()),
q.y.clone().unwrap().pow(m.clone()),
);
let mut f = Fq12::one();
if p != q {
let ate_loop_count = BigInt::from_str("29793968203157093288").unwrap();

let nq2 = EllipticCurvePoint::<F, E>::new(
q1.x.clone().unwrap().pow(m.clone()),
-q1.y.clone().unwrap().pow(m.clone()),
);
let out = miller(&q, &p, ate_loop_count);
f = out.0;
let mut r = out.1;
// Assert: r == multiply(&q, &ate_loop_count)

f = f.mul_ref(&linefunc(&r, &q1, &p));
r = r.add_ref(&q1);
f = f.mul_ref(&linefunc(&r, &nq2, &p));
let q1 = G12Point::new(
q.x.clone().unwrap().pow(m.clone()),
q.y.clone().unwrap().pow(m.clone()),
);

f
}
let nq2 = G12Point::new(
q1.x.clone().unwrap().pow(m.clone()),
-q1.y.clone().unwrap().pow(m.clone()),
);

pub fn optimal_ate_pairing(p: G1Point, q: G2Point) -> Fq12 {
let p_prime: G12Point = cast_G1_to_G12(p);
let q_prime: G12Point = twist_G2_to_G12(q);
let m = BN128Modulus::modulus();
f = f.mul_ref(&get_lambda(&r, &q1, &p));
r = r.add_ref(&q1);
f = f.mul_ref(&get_lambda(&r, &nq2, &p));
}

let f = vanila_miller(&p_prime, &q_prime, &m);
let exp = (m.pow(12) - BigInt::one()) / (BN128::order());
f.pow(exp)
}
Expand Down Expand Up @@ -358,7 +310,7 @@ mod tests {
#[test]
fn test_g12() {
let g2 = BN128::generator_g2();
let g12 = twist_G2_to_G12(g2);
let g12 = twist_g2_to_g12(g2);
let g12_9 = g12.clone() * 9;
assert_eq!(
g12_9.clone().y.unwrap().pow(2) - g12_9.clone().x.unwrap().pow(3),
Expand All @@ -379,21 +331,21 @@ mod tests {
fn test_pairing() {
let g1 = BN128::generator_g1();
let g2 = BN128::generator_g2();
let p1 = optimal_ate_pairing(g1.clone(), g2.clone());
let pn1 = optimal_ate_pairing(-g1.clone(), g2.clone());
let p1 = optimal_ate_pairing(&g1.clone(), &g2.clone());
let pn1 = optimal_ate_pairing(&-g1.clone(), &g2.clone());
assert_eq!(p1.clone() * pn1.clone(), Fq12::one());
let np1 = optimal_ate_pairing(g1.clone(), -g2.clone());
let np1 = optimal_ate_pairing(&g1.clone(), &-g2.clone());
assert_eq!(p1.clone() * np1.clone(), Fq12::one());
assert_eq!(pn1.clone(), np1.clone());
let p2 = optimal_ate_pairing(g1.clone() * 2, g2.clone());
let p2 = optimal_ate_pairing(&(g1.clone() * 2), &g2.clone());
assert_eq!(p1.clone() * p1.clone(), p2);
assert!(p1 != p2);
assert!(p1 != np1);
assert!(p2 != np1);
let po2 = optimal_ate_pairing(g1.clone(), g2.clone() * 2);
let po2 = optimal_ate_pairing(&g1.clone(), &(g2.clone() * 2));
assert_eq!(p1.clone() * p1.clone(), po2);
let p3 = optimal_ate_pairing(g1.clone() * 37, g2.clone() * 27);
let po3 = optimal_ate_pairing(g1.clone() * 999, g2.clone());
let p3 = optimal_ate_pairing(&(g1.clone() * 37), &(g2.clone() * 27));
let po3 = optimal_ate_pairing(&(g1.clone() * 999), &(g2.clone()));
assert_eq!(p3, po3);
}
}
74 changes: 15 additions & 59 deletions myzkp/src/modules/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ impl<F: Field, E: EllipticCurve> EllipticCurvePoint<F, E> {

pub fn line_slope(&self, other: &Self) -> F {
let a = F::from_value(E::get_a());
// let b = E::get_b();

let x1 = self.x.as_ref().unwrap();
let y1 = self.y.as_ref().unwrap();
Expand Down Expand Up @@ -84,49 +83,6 @@ impl<F: Field, E: EllipticCurve> EllipticCurvePoint<F, E> {
}

pub fn add_ref(&self, other: &Self) -> Self {
/*
if self.is_point_at_infinity() {
return other;
}
if other.is_point_at_infinity() {
return self;
}
let m = self.line_slope(other.clone());
// If x coordinates are the same
if self.x == other.x {
// Check if they are inverses of each other
if self.y != other.y {
// TODO: check self.y = -other.y
return EllipticCurvePoint::point_at_infinity();
} else {
// P = Q, handle point doubling
let x1 = self.x.clone().unwrap();
let y1 = self.y.clone().unwrap();
// let m = ((x1.clone() * x1.clone()).mul_scalar(3_i64) + self.curve.a.clone())
// / (y1.clone().mul_scalar(2_i64));
let x3 = m.clone() * m.clone() - x1.clone() - x1.clone();
let y3 = m * (x1 - x3.clone()) - y1;
return EllipticCurvePoint::new(x3, y3);
}
} else {
// P != Q, handle regular addition
let x1 = self.x.clone().unwrap();
let y1 = self.y.clone().unwrap();
let x2 = other.x.clone().unwrap();
// let y2 = other.y.clone().unwrap();
// let m = (y2.clone() - y1.clone()) / (x2.clone() - x1.clone());
let x3 = m.clone() * m.clone() - x1.clone() - x2.clone();
let y3 = m * (x1 - x3.clone()) - y1;
return EllipticCurvePoint::new(x3, y3);
}*/

if self.is_point_at_infinity() {
return other.clone();
}
Expand Down Expand Up @@ -249,15 +205,15 @@ pub fn miller<F: Field, E: EllipticCurve>(
p: &EllipticCurvePoint<F, E>,
q: &EllipticCurvePoint<F, E>,
m: BigInt,
) -> F {
) -> (F, EllipticCurvePoint<F, E>) {
if p == q {
return F::one();
return (F::one(), p.clone());
}

let mut f = F::one();
let mut t = p.clone();

for i in (1..m.bits()).rev() {
for i in (0..(m.bits() - 1)).rev() {
f = (f.mul_ref(&f)) * (get_lambda(&t, &t, &q));
t = t.add_ref(&t);
if m.bit(i) {
Expand All @@ -266,7 +222,7 @@ pub fn miller<F: Field, E: EllipticCurve>(
}
}

f
(f, t)
}

pub fn weil_pairing<F: Field, E: EllipticCurve>(
Expand All @@ -276,10 +232,10 @@ pub fn weil_pairing<F: Field, E: EllipticCurve>(
s: Option<&EllipticCurvePoint<F, E>>,
) -> F {
let s_value = s.unwrap();
let fp_qs = miller(&p, &q.add_ref(&s_value), m.clone());
let fp_s = miller(&p, &s_value, m.clone());
let fq_ps = miller(&q, &p.add_ref(&(s_value.clone().neg())), m.clone());
let fq_s = miller(&q, &(-s_value.clone()), m.clone());
let (fp_qs, _) = miller(&p, &q.add_ref(&s_value), m.clone());
let (fp_s, _) = miller(&p, &s_value, m.clone());
let (fq_ps, _) = miller(&q, &p.add_ref(&(s_value.clone().neg())), m.clone());
let (fq_s, _) = miller(&q, &(-s_value.clone()), m.clone());

return (fp_qs / fp_s) / (fq_ps / fq_s);
}
Expand All @@ -292,8 +248,8 @@ pub fn general_tate_pairing<F: Field, E: EllipticCurve>(
s: Option<&EllipticCurvePoint<F, E>>,
) -> F {
let s_value = s.unwrap();
let fp_qs = miller(&p, &q.add_ref(&s_value), ell.clone());
let fp_s = miller(&p, &s_value, ell.clone());
let (fp_qs, _) = miller(&p, &q.add_ref(&s_value), ell.clone());
let (fp_s, _) = miller(&p, &s_value, ell.clone());
let f = fp_qs.div_ref(&fp_s);

return f.pow((modulus - BigInt::one()) / ell);
Expand All @@ -305,7 +261,7 @@ pub fn tate_pairing<F: Field, E: EllipticCurve>(
ell: BigInt,
modulus: BigInt,
) -> F {
let fp_q = miller(&p, &q, ell.clone());
let (fp_q, _) = miller(&p, &q, ell.clone());

return fp_q.pow((modulus - BigInt::one()) / ell);
}
Expand Down Expand Up @@ -359,17 +315,17 @@ mod tests {
);
let order = 5.to_bigint().unwrap();

let fp_qs = miller(&p, &(q.add_ref(&s)), order.clone());
let fp_s = miller(&p, &s, order.clone());
let (fp_qs, _) = miller(&p, &(q.add_ref(&s)), order.clone());
let (fp_s, _) = miller(&p, &s, order.clone());
assert_eq!(fp_qs.sanitize().value, 103_i32.to_bigint().unwrap());
assert_eq!(fp_s.sanitize().value, 219_i32.to_bigint().unwrap());
assert_eq!(
(fp_qs / fp_s).sanitize().value,
473_i32.to_bigint().unwrap()
);

let fq_ps = miller(&q, &p.add_ref(&s.clone().neg()), order.clone());
let fq_s = miller(&q, &(-s.clone()), order.clone());
let (fq_ps, _) = miller(&q, &p.add_ref(&s.clone().neg()), order.clone());
let (fq_s, _) = miller(&q, &(-s.clone()), order.clone());
assert_eq!(fq_ps.sanitize().value, 284_i32.to_bigint().unwrap());
assert_eq!(fq_s.sanitize().value, 204_i32.to_bigint().unwrap());
assert_eq!((fq_ps / fq_s).sanitize().value, 88_i32.to_bigint().unwrap());
Expand Down
2 changes: 1 addition & 1 deletion myzkp/src/modules/educational_protocols/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod dl;
pub mod kea;
pub mod naive;
//pub mod nizk;
pub mod nizk;
pub mod sz;
pub mod zk;
Loading

0 comments on commit a8196cc

Please sign in to comment.