Browse Source

fixed source of bug which was passing a negative BigInt to mul_scalar...better fix might be to force mul_scalar to only accept a BigUInt or to allow the logic in mul_scalar to work with a negative BigInt

pull/8/head
Nanak Nihal Singh Khalsa 1 year ago
parent
commit
5439c2a19f
2 changed files with 156 additions and 9 deletions
  1. +1
    -1
      Cargo.toml
  2. +155
    -8
      src/lib.rs

+ 1
- 1
Cargo.toml

@ -10,7 +10,7 @@ readme = "README.md"
[dependencies]
ff = {package="ff_ce", version= "0.11", features = ["derive"]}
rand_new = {package="rand", version="0.8"}
rand_new = {package="rand", version="0.8.5"}
rand = "0.4.6"
num = "0.4"
num-bigint = {version = "0.4", features = ["rand"]}

+ 155
- 8
src/lib.rs

@ -2,7 +2,8 @@
// For LICENSE check https://github.com/arnaucube/babyjubjub-rs
use ff::*;
use std::iter::Sum;
use rand::ThreadRng;
use std::{iter::Sum, ops::{Neg, AddAssign}};
use num::Num;
use std::fmt;
// use serde::{Serialize, ser::SerializeSeq, Deserialize};
@ -81,16 +82,19 @@ lazy_static! {
pub static ref ORDER: Fr = Fr::from_str(
"21888242871839275222246405745257275088614511777268538073601725287587578984328",
)
.unwrap();
).unwrap();
pub static ref ORDER_BI: BigInt = BigInt::parse_bytes(
b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
10,
).unwrap();
// SUBORDER = ORDER >> 3
pub static ref SUBORDER: BigInt = &BigInt::parse_bytes(
b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
10,
)
.unwrap()
>> 3;
).unwrap()
>> 3;
pub static ref POSEIDON: poseidon_rs::Poseidon = Poseidon::new();
// MAX_MSG is maximum message length that can be encoded into a point. This will be Q / KOBLITZ_NUMBER
@ -248,7 +252,6 @@ impl FrBigIntConversion for Fl {
// }
// }
impl Serialize for Point {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -308,7 +311,7 @@ impl<'de> Visitor<'de> for PointVisitor {
}
}
// For addition shorthand
impl Point {
pub fn projective(&self) -> PointProjective {
PointProjective {
@ -727,6 +730,137 @@ pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
l.equals(r)
}
pub struct DLEQProof {
pub A: Point,
pub B: Point,
pub xA: Point,
pub xB: Point,
pub challenge: BigInt,
pub response: BigInt,
}
impl DLEQProof {
// Prove that ∃ x s.t. x*A = variable xA and x*B = variable xB
pub fn new(x: BigInt, point_A: Point, point_B: Point) -> DLEQProof {
let xA = point_A.mul_scalar(&x);
let xB = point_B.mul_scalar(&x);
let mut rng = rand_new::thread_rng();
let k = rng.gen_biguint(512).to_bigint().unwrap() % Q.clone();
let kA = point_A.mul_scalar(&k);
let kB = point_B.mul_scalar(&k);
let challenge = DLEQProof::get_challenge(&point_A, &point_B, &xA, &xB, &kA, &kB);
let k_field = Fr::from_str(&k.to_string()).unwrap();
let x_field = Fr::from_str(&k.to_string()).unwrap();
let challenge_field = Fr::from_str(&challenge.to_string()).unwrap();
let mut response_field = challenge_field.clone();
response_field.negate();
response_field.mul_assign(&x_field);
response_field.add_assign(&k_field);
// let response = Fr::from k - &challenge * &x) % Q.clone();
// let response = BigInt::from_str("-10").unwrap();//(ORDER_BI.clone() + BigInt::from_str("100").unwrap()).neg();
let response = response_field.to_bigint();
println!("response: {:?}", response);
// -7:
// let neg7 = "-7".parse::<BigInt>().unwrap();
// let neg7_ = Q.clone() + &neg7;
// let product = B8.mul_scalar(&neg7);
// let product_ = B8.mul_scalar(&neg7_);
// println!("\nproduct: {:?} ====================== {:?} \n", product.x, product_.x);
// let cxA = xA.mul_scalar(&challenge);
// let cxA_ = point_A.mul_scalar(&challenge).mul_scalar(&x);
// println!("cxA: {:?} ====================== {:?} ", cxA, cxA_);
let xchallenge = &x * &challenge;
let response_plus_xchallenge = &response + &xchallenge;
let xchallengeA = point_A.mul_scalar(&xchallenge);
let responseA = point_A.mul_scalar(&response);
let sum_method1 = responseA.add(&xchallengeA);
let sum_method2 = point_A.mul_scalar(&(response_plus_xchallenge));
// DELETE THIS:
// let kA1 = point_A.mul_scalar(&(&response + &challenge * &x));
// let kA2 = point_A.mul_scalar(&response).add(
// &point_A.mul_scalar(&(&challenge * &x))
// );
// let _a = Q.clone() - BigInt::from_str("10").unwrap();
// let _b = BigInt::from_str("2000").unwrap();
// let _A = B8.mul_scalar(&_a);
// let _B = B8.mul_scalar(&_b);
// let _prod = _A.add(&_B);
// let __prod = B8.mul_scalar(&(_a+_b));
// println!("\n\n\n\n\n\nprods: {:?} =================== {:?}\n\n\n\n", _prod.x, __prod.x);
// println!("one {:?}", point_A.mul_scalar(&BigInt::from_bytes_be(Sign::Plus,&[1])).x);
// println!("two {:?}", point_A.mul_scalar(&BigInt::from_bytes_be(Sign::Plus,&[2])).x);
// println!("one {:?}", point_A.mul_scalar(&BigInt::from_bytes_be(Sign::Plus,&[1])).x);
// let kB_ =
// point_B.mul_scalar(&response).add(
// &xA.mul_scalar(&challenge)
// );
// println!("kA==kA_? {:?}. kB==kB_? {:?}", kA_.equals(kA), kB_.equals(kB));
// println!("1x: {:?}\n2x: {:?}", sum_method1.x, sum_method2.x);
println!("kA: {:?}. kB {:?}", kA, kB);
DLEQProof {
A: point_A,
B: point_B,
xA,
xB,
challenge,
response
}
}
pub fn verify(&self) -> bool {
// This should equal kA
let kA_ =
self.A.mul_scalar(&self.response).add(
&self.xA.mul_scalar(&self.challenge)
);
// This should equal kB
let kB_ =
self.B.mul_scalar(&self.response).add(
&self.xB.mul_scalar(&self.challenge)
);
println!("kA_: {:?}. kB_ {:?}", kA_, kB_);
// Check that kA_ == kA and kB_ == kB by recomputing the challenge and checking that it matches
let challenge = DLEQProof::get_challenge(&self.A, &self.B, &self.xA, &self.xB, &kA_, &kB_);
// println!("got challenge: {:?} which should equal {:?}", challenge, self.challenge);
return challenge == self.challenge;
}
// Generates randomness for DLEQ Fiat-Shamir transform
fn get_challenge(point_A: &Point, point_B: &Point, xA: &Point, xB: &Point, kA: &Point, kB: &Point) -> BigInt {
// This could probably be faster if we neglect either the x or y coordinate, but rn doing both to be safe until i study this more
let inputs: Vec<Fr> = vec![
point_A.x,point_A.y,
xA.x,xA.y,
point_B.x,point_B.y,
xB.x,xB.y,
kA.x,kA.y,
kB.x,kB.y
];
let input: Vec<u8> = inputs.iter().map(|f| {
let as_hex = to_hex(f);
hex::decode(as_hex).unwrap()
})
.flatten()
.collect();
let challenge_hash = blh(&input);
// println!("{:?} is hash of input {:?}", challenge_hash, input);
BigInt::from_bytes_be(Sign::Plus, &challenge_hash.as_slice())
% ORDER_BI.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -734,6 +868,19 @@ mod tests {
use rand_new::Rng;
use num_traits::FromPrimitive;
#[test]
fn test_dleq() {
let a = BigInt::parse_bytes(b"123456789", 10).unwrap();
let point_A = B8.mul_scalar(&a);
let b = BigInt::parse_bytes(b"55555555555555512345678944444444444", 10).unwrap();
let point_B = B8.mul_scalar(&b);
let mut rng = rand_new::thread_rng();
let x = rng.gen_biguint(512).to_bigint().unwrap() % ORDER_BI.clone();
let proof = DLEQProof::new(x, point_A, point_B);
println!("proof: {:?}", proof.verify());
assert!(proof.verify());
}
#[test]
fn test_on_curve() {
assert_eq!(B8.on_curve(), true);

Loading…
Cancel
Save