Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support bandersnatch group #139

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
03370de
chore: Include bls12-381 vendored dependency
CPerezz Sep 11, 2023
0d4a224
add: Compute endomorphism parameters for Bls12-381
CPerezz Sep 11, 2023
405f2c6
refactor endo impl with failing tests
CPerezz Sep 14, 2023
97b0de8
fixup
CPerezz Sep 16, 2023
2fa3517
change: Update params for Endo after missnaming
CPerezz Sep 25, 2023
9329af1
update: Bls dep pulls now latest release tag
CPerezz Dec 18, 2023
b02d296
chore: Re-export all bls12_381 lib artifacts
CPerezz Dec 18, 2023
95a9fc3
Merge branch 'main' into support_bls12-381
CPerezz Jan 17, 2024
e927276
patch to local bls12-381
dragan2234 Feb 19, 2024
64063b0
add support for FromUniformBytes
dragan2234 Feb 19, 2024
099b50c
bandersnatch WIP
dragan2234 Feb 22, 2024
6d5a830
r parameters calculation done
dragan2234 Feb 22, 2024
773ad67
save work, square tests failing
dragan2234 Feb 22, 2024
a1e9102
fix delta
dragan2234 Feb 22, 2024
dcdc64d
fix t for tonelli shanks
dragan2234 Feb 22, 2024
690e7ae
add curve, SSVDW_Z parameter missing
dragan2234 Feb 23, 2024
44f7d73
add SSVDW_Z parameter, test_curve multiplication failing still for so…
dragan2234 Feb 26, 2024
ee575c6
fix cofactor
dragan2234 Feb 26, 2024
536a2d5
add jubjub implementation skeleton
dragan2234 Feb 29, 2024
32e5726
add TE parameters
dragan2234 Mar 1, 2024
ed03cf3
add bandersnatch TE in progress
dragan2234 Mar 1, 2024
2268bce
save work, updates
dragan2234 Mar 4, 2024
87becc7
test passing for double on extended edwards
dragan2234 Mar 5, 2024
7cc9b0d
equality tests passing for doubling, addition and scalar mul
dragan2234 Mar 5, 2024
81478ff
cleanup
dragan2234 Mar 5, 2024
b3453cc
cleanup
dragan2234 Mar 5, 2024
87a1f6a
impl subtraction
dragan2234 Mar 5, 2024
2001cc0
add quick test
dragan2234 Mar 5, 2024
38076b7
refactor
dragan2234 Mar 27, 2024
ca87ba3
add proper is_on_curve is_identity checks
dragan2234 Mar 29, 2024
529713e
formatting
dragan2234 May 21, 2024
daef07e
add serialization to bls12381
dragan2234 May 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ serde = { version = "1.0", default-features = false, optional = true }
serde_arrays = { version = "0.1.0", optional = true }
hex = { version = "0.4", optional = true, default-features = false, features = ["alloc", "serde"] }
blake2b_simd = "1"
bls12_381 = { git = "https://github.com/dragan2234/bls12_381", features = ["groups", "basefield"], branch = "add-FromUniformBytes-trait" }
rayon = "1.8"

[dependencies.bitvec]
version = "1"
default-features = false

[features]
default = ["bits"]
asm = []
Expand Down
181 changes: 181 additions & 0 deletions src/bandersnatch/curve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
use crate::bandersnatch::Fp;
use crate::bandersnatch::Fr;
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding};
use crate::hash_to_curve::sswu_hash_to_curve;
use crate::{Coordinates, CurveAffine, CurveExt};
use core::cmp;
use core::fmt::Debug;
use core::iter::Sum;
use core::ops::{Add, Mul, Neg, Sub};
use rand::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

#[cfg(feature = "derive_serde")]
use serde::{Deserialize, Serialize};

impl group::cofactor::CofactorGroup for Bandersnatch {
type Subgroup = Bandersnatch;

fn clear_cofactor(&self) -> Self {
self * Fr::from(4)
}

fn into_subgroup(self) -> CtOption<Self::Subgroup> {
CtOption::new(self, 1.into())
}

fn is_torsion_free(&self) -> Choice {
1.into()
}
}

// Reference: https://eprint.iacr.org/2021/1152.pdf
// SW x: a76451786f95a802c0982bbd0abd68e41b92adc86c8859b4f44679b21658710
const BANDERSNATCH_GENERATOR_X: Fp = Fp::from_raw([
0x4f44679b21658710,
0x41b92adc86c8859b,
0x2c0982bbd0abd68e,
0xa76451786f95a80,
]);

// SW y: 44d150c8b4bd14f79720d021a839e7b7eb4ee43844b30243126a72ac2375490a
const BANDERSNATCH_GENERATOR_Y: Fp = Fp::from_raw([
0x126a72ac2375490a,
0xeb4ee43844b30243,
0x9720d021a839e7b7,
0x44d150c8b4bd14f7,
]);

// − 3763200000
// 73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFE1FB22001
const BANDERSNATCH_A: Fp = Fp::from_raw([
0xFFFFFFFE1FB22001,
0x53BDA402FFFE5BFE,
0x3339D80809A1D805,
0x73EDA753299D7D48,
]);

// − 78675968000000
// 73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFB870D2E00001
const BANDERSNATCH_B: Fp = Fp::from_raw([
0xFFFFB870D2E00001,
0x53BDA402FFFE5BFE,
0x3339D80809A1D805,
0x73EDA753299D7D48,
]);

use crate::{
impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
new_curve_impl,
};

new_curve_impl!(
(pub),
Bandersnatch,
BandersnatchAffine,
true,
Fp,
Fr,
(BANDERSNATCH_GENERATOR_X,BANDERSNATCH_GENERATOR_Y),
BANDERSNATCH_A,
BANDERSNATCH_B,
"bandersnatch",
|curve_id, domain_prefix| sswu_hash_to_curve(curve_id, domain_prefix, Bandersnatch::SSVDW_Z),
);

impl Bandersnatch {
// TODO: switch to bandersnatch param
// Optimal Z with: <https://datatracker.ietf.org/doc/html/rfc9380#sswu-z-code>
// Script: https://github.com/privacy-scaling-explorations/halo2curves/pull/139#issuecomment-1965257028
// Z = 7 (reference: <https://www.rfc-editor.org/rfc/rfc9380.html#section-8.2>)
const SSVDW_Z: Fp = Fp::from_raw([
0x0000000000000007,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
]);
}

#[cfg(test)]
mod tests {
use super::*;
use crate::bandersnatch::{Fp, Fr};
use crate::group::Curve;
use ff::FromUniformBytes;
use rand_core::OsRng;

#[test]
fn test_hash_to_curve() {
crate::tests::curve::hash_to_curve_test::<Bandersnatch>();
}

#[test]
fn test_curve() {
crate::tests::curve::curve_tests::<Bandersnatch>();
}

#[test]
fn test_serialization() {
crate::tests::curve::random_serialization_test::<Bandersnatch>();
#[cfg(feature = "derive_serde")]
crate::tests::curve::random_serde_test::<Bandersnatch>();
}

#[test]
fn ecdsa_example() {
fn mod_n(x: Fp) -> Fr {
let mut x_repr = [0u8; 32];
x_repr.copy_from_slice(x.to_repr().as_ref());
let mut x_bytes = [0u8; 64];
x_bytes[..32].copy_from_slice(&x_repr[..]);
Fr::from_uniform_bytes(&x_bytes)
}

let g = Bandersnatch::generator();

for _ in 0..1000 {
// Generate a key pair
let sk = Fr::random(OsRng);
let pk = (g * sk).to_affine();

// Generate a valid signature
// Suppose `m_hash` is the message hash
let msg_hash = Fr::random(OsRng);

let (r, s) = {
// Draw arandomness
let k = Fr::random(OsRng);
let k_inv = k.invert().unwrap();

// Calculate `r`
let r_point = (g * k).to_affine().coordinates().unwrap();
let x = r_point.x();
let r = mod_n(*x);

// Calculate `s`
let s = k_inv * (msg_hash + (r * sk));

(r, s)
};

{
// Verify
let s_inv = s.invert().unwrap();
let u_1 = msg_hash * s_inv;
let u_2 = r * s_inv;

let v_1 = g * u_1;
let v_2 = pk * u_2;

let r_point = (v_1 + v_2).to_affine().coordinates().unwrap();
let x_candidate = r_point.x();
let r_candidate = mod_n(*x_candidate);

assert_eq!(r, r_candidate);
}
}
}
}
Loading