diff --git a/Cargo.toml b/Cargo.toml index b656fdf..0f4f518 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,4 +25,12 @@ lazy_static = "1.5.0" hex-literal = "0.4.1" serde = { version = "1.0.204", features = ["derive"] } serde_json = "1.0.120" -sha2 = "0.11.0-pre.4" \ No newline at end of file +sha2 = "0.11.0-pre.4" +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "mod" +harness = false + +[profile.bench] +debug = true diff --git a/benches/field.rs b/benches/field.rs new file mode 100644 index 0000000..d603508 --- /dev/null +++ b/benches/field.rs @@ -0,0 +1,234 @@ +#![allow(dead_code)] +use criterion::{black_box, Criterion}; +use crypto_bigint::rand_core::OsRng; +use crypto_bigint::U256; +use sylow::{FieldExtensionTrait, Fp, Fp12, Fp2, Fp6}; +pub mod fp { + use super::*; + const A: Fp = Fp::THREE; + const B: Fp = Fp::FOUR; + + pub fn test_fp_multiplication(c: &mut Criterion) { + c.bench_function("test_fp_multiplication", |b| { + b.iter(|| black_box(A) * black_box(B)) + }); + } + pub fn test_fp_addition(c: &mut Criterion) { + c.bench_function("test_fp_addition", |b| { + b.iter(|| black_box(A) + black_box(B)) + }); + } + pub fn test_fp_subtraction(c: &mut Criterion) { + c.bench_function("test_fp_subtraction", |b| { + b.iter(|| black_box(A) - black_box(B)) + }); + } + pub fn test_fp_division(c: &mut Criterion) { + c.bench_function("test_fp_division", |b| { + b.iter(|| black_box(A) / black_box(B)) + }); + } + pub fn test_fp_random(c: &mut Criterion) { + let mut rng = OsRng; + c.bench_function("test_fp_random", |b| { + b.iter(|| >::rand(&mut rng)) + }); + } + pub fn test_fp_new(c: &mut Criterion) { + c.bench_function("test_fp_new", |b| { + b.iter(|| Fp::new(U256::from_words([1, 2, 3, 4]))) + }); + } +} + +pub mod fp2 { + use super::*; + const A: Fp2 = Fp2::new(&[Fp::FOUR, Fp::NINE]); + const B: Fp2 = Fp2::new(&[Fp::NINE, Fp::FOUR]); + + pub fn test_fp2_multiplication(c: &mut Criterion) { + c.bench_function("test_fp2_multiplication", |b| { + b.iter(|| black_box(A) * black_box(B)) + }); + } + pub fn test_fp2_addition(c: &mut Criterion) { + c.bench_function("test_fp2_addition", |b| { + b.iter(|| black_box(A) + black_box(B)) + }); + } + pub fn test_fp2_subtraction(c: &mut Criterion) { + c.bench_function("test_fp2_subtraction", |b| { + b.iter(|| black_box(A) - black_box(B)) + }); + } + pub fn test_fp2_division(c: &mut Criterion) { + c.bench_function("test_fp2_division", |b| { + b.iter(|| black_box(A) / black_box(B)) + }); + } + pub fn test_fp2_random(c: &mut Criterion) { + let mut rng = OsRng; + c.bench_function("test_fp2_random", |b| { + b.iter(|| >::rand(&mut rng)) + }); + } + pub fn test_fp2_new(c: &mut Criterion) { + c.bench_function("test_fp2_new", |b| { + b.iter(|| { + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]) + }) + }); + } +} +pub mod fp6 { + use super::*; + const A: Fp6 = Fp6::new(&[ + Fp2::new(&[Fp::FOUR, Fp::NINE]), + Fp2::new(&[Fp::FOUR, Fp::NINE]), + Fp2::new(&[Fp::FOUR, Fp::NINE]), + ]); + + const B: Fp6 = Fp6::new(&[ + Fp2::new(&[Fp::NINE, Fp::FOUR]), + Fp2::new(&[Fp::NINE, Fp::FOUR]), + Fp2::new(&[Fp::NINE, Fp::FOUR]), + ]); + + pub fn test_fp6_multiplication(c: &mut Criterion) { + c.bench_function("test_fp6_multiplication", |b| { + b.iter(|| black_box(A) * black_box(B)) + }); + } + pub fn test_fp6_addition(c: &mut Criterion) { + c.bench_function("test_fp6_addition", |b| { + b.iter(|| black_box(A) + black_box(B)) + }); + } + pub fn test_fp6_subtraction(c: &mut Criterion) { + c.bench_function("test_fp6_subtraction", |b| { + b.iter(|| black_box(A) - black_box(B)) + }); + } + pub fn test_fp6_division(c: &mut Criterion) { + c.bench_function("test_fp6_division", |b| { + b.iter(|| black_box(A) / black_box(B)) + }); + } + pub fn test_fp6_random(c: &mut Criterion) { + let mut rng = OsRng; + c.bench_function("test_fp6_random", |b| { + b.iter(|| >::rand(&mut rng)) + }); + } + pub fn test_fp6_new(c: &mut Criterion) { + c.bench_function("test_fp6_new", |b| { + b.iter(|| { + Fp6::new(&[ + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + ]) + }) + }); + } +} +pub mod fp12 { + use super::*; + const A: Fp12 = Fp12::new(&[ + Fp6::new(&[ + Fp2::new(&[Fp::FOUR, Fp::NINE]), + Fp2::new(&[Fp::FOUR, Fp::NINE]), + Fp2::new(&[Fp::FOUR, Fp::NINE]), + ]), + Fp6::new(&[ + Fp2::new(&[Fp::FOUR, Fp::NINE]), + Fp2::new(&[Fp::FOUR, Fp::NINE]), + Fp2::new(&[Fp::FOUR, Fp::NINE]), + ]), + ]); + + const B: Fp12 = Fp12::new(&[ + Fp6::new(&[ + Fp2::new(&[Fp::NINE, Fp::FOUR]), + Fp2::new(&[Fp::NINE, Fp::FOUR]), + Fp2::new(&[Fp::NINE, Fp::FOUR]), + ]), + Fp6::new(&[ + Fp2::new(&[Fp::NINE, Fp::FOUR]), + Fp2::new(&[Fp::NINE, Fp::FOUR]), + Fp2::new(&[Fp::NINE, Fp::FOUR]), + ]), + ]); + pub fn test_fp12_multiplication(c: &mut Criterion) { + c.bench_function("test_fp12_multiplication", |b| { + b.iter(|| black_box(A) * black_box(B)) + }); + } + pub fn test_fp12_addition(c: &mut Criterion) { + c.bench_function("test_fp12_addition", |b| { + b.iter(|| black_box(A) + black_box(B)) + }); + } + pub fn test_fp12_subtraction(c: &mut Criterion) { + c.bench_function("test_fp12_subtraction", |b| { + b.iter(|| black_box(A) - black_box(B)) + }); + } + pub fn test_fp12_division(c: &mut Criterion) { + c.bench_function("test_fp12_division", |b| { + b.iter(|| black_box(A) / black_box(B)) + }); + } + pub fn test_fp12_random(c: &mut Criterion) { + let mut rng = OsRng; + c.bench_function("test_fp12_random", |b| b.iter(|| Fp12::rand(&mut rng))); + } + pub fn test_fp12_new(c: &mut Criterion) { + c.bench_function("test_fp12_new", |b| { + b.iter(|| { + Fp12::new(&[ + Fp6::new(&[ + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + ]), + Fp6::new(&[ + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + Fp2::new(&[ + Fp::new(U256::from_words([1, 2, 3, 4])), + Fp::new(U256::from_words([1, 2, 3, 4])), + ]), + ]), + ]) + }) + }); + } +} diff --git a/benches/group.rs b/benches/group.rs new file mode 100644 index 0000000..7714fa5 --- /dev/null +++ b/benches/group.rs @@ -0,0 +1,112 @@ +#![allow(dead_code)] +use criterion::{black_box, Criterion}; +use sylow::{Fp, G1Affine, G1Projective, G2Affine, G2Projective, GroupTrait}; + +pub mod g1 { + use super::*; + use sylow::Fp; + + const KNOWN_VALUES: [Fp; 3] = [Fp::ONE, Fp::TWO, Fp::ONE]; + + pub fn test_g1affine_conversion_to_g1projective(c: &mut Criterion) { + let generator = G1Affine::generator(); + c.bench_function("g1affine_conversion_to_g1projective", |b| { + b.iter(|| G1Projective::from(black_box(generator))) + }); + } + pub fn test_g1projective_generation(c: &mut Criterion) { + c.bench_function("test_g1projective_generation", |b| { + b.iter(|| { + G1Projective::new(black_box(KNOWN_VALUES)).expect("Failed to create G1Projective") + }) + }); + } + pub fn test_g1projective_addition(c: &mut Criterion) { + let a = G1Projective::generator(); + c.bench_function("test_g1projective_addition", |b| { + b.iter(|| black_box(a) + black_box(a)) + }); + } + pub fn test_g1projective_multiplication(c: &mut Criterion) { + let g1_projective = G1Projective::generator(); + const SCALAR: Fp = Fp::THREE; + c.bench_function("test_g1projective_multiplication", |b| { + b.iter(|| black_box(g1_projective) * black_box(SCALAR)) + }); + } + pub fn test_g1projective_conversion_to_g1affine(c: &mut Criterion) { + let generator = G1Projective::generator(); + c.bench_function("g1projective_conversion_to_g1affine", |b| { + b.iter(|| G1Affine::from(black_box(generator))) + }); + } +} + +pub mod g2 { + use super::*; + use crypto_bigint::U256; + use sylow::Fp2; + + const KNOWN_X: Fp2 = Fp2::new(&[ + Fp::new(U256::from_words([ + 15176525146662381588, + 16999198464856720888, + 10551491725746096164, + 2109507925758354620, + ])), + Fp::new(U256::from_words([ + 5829542572658843162, + 6956048341656855305, + 457351042342223481, + 213802418293478404, + ])), + ]); + const KNOWN_Y: Fp2 = Fp2::new(&[ + Fp::new(U256::from_words([ + 16717123787957323851, + 9581483432139821434, + 7173403850490595536, + 650007998934857427, + ])), + Fp::new(U256::from_words([ + 5081543861758110462, + 8687473586797606316, + 15555792616844701404, + 3266271495335422485, + ])), + ]); + const KNOWN_Z: Fp2 = Fp2::new(&[Fp::ONE, Fp::ZERO]); + pub fn test_g2affine_conversion_to_g2projective(c: &mut Criterion) { + let generator = G2Affine::generator(); + c.bench_function("g2affine_conversion_to_g2projective", |b| { + b.iter(|| G2Projective::from(black_box(generator))) + }); + } + pub fn test_g2projective_valid_generation(c: &mut Criterion) { + c.bench_function("test_g2projective_generation", |b| { + b.iter(|| { + G2Projective::new(black_box([KNOWN_X, KNOWN_Y, KNOWN_Z])) + .expect("Failed to create G2Projective") + }) + }); + } + pub fn test_g2projective_addition(c: &mut Criterion) { + let a = G2Projective::generator(); + c.bench_function("test_g2projective_addition", |b| { + b.iter(|| black_box(a) + black_box(a)) + }); + } + pub fn test_g2projective_multiplication(c: &mut Criterion) { + let g2_projective = G2Projective::generator(); + const SCALAR: Fp = Fp::THREE; + c.bench_function("test_g2projective_multiplication", |b| { + b.iter(|| black_box(g2_projective) * black_box(SCALAR)) + }); + } + pub fn test_g2projective_conversion_to_g2affine(c: &mut Criterion) { + let generator = G2Projective::generator(); + c.bench_function("g2projective_conversion_to_g2affine", |b| { + b.iter(|| G2Affine::from(black_box(generator))) + }); + } +} diff --git a/benches/mod.rs b/benches/mod.rs new file mode 100644 index 0000000..8ef3b91 --- /dev/null +++ b/benches/mod.rs @@ -0,0 +1,84 @@ +use criterion::{criterion_group, criterion_main}; + +mod group; +use group::g1::*; +use group::g2::*; + +mod field; +use field::fp::*; +use field::fp12::*; +use field::fp2::*; +use field::fp6::*; + +mod pairing; +use pairing::*; + +mod sig; +use sig::*; + +criterion_group!(pairing_benches, test_pairing); +criterion_group!(signature_benches, test_signing); + +criterion_group!( + g1_benches, + test_g1affine_conversion_to_g1projective, + test_g1projective_generation, + test_g1projective_addition, + test_g1projective_multiplication, + test_g1projective_conversion_to_g1affine +); +criterion_group!( + g2_benches, + test_g2affine_conversion_to_g2projective, + test_g2projective_valid_generation, + test_g2projective_addition, + test_g2projective_multiplication +); + +criterion_group!( + fp_benches, + test_fp_multiplication, + test_fp_addition, + test_fp_subtraction, + test_fp_division, + test_fp_random, + test_fp_new +); +criterion_group!( + fp2_benches, + test_fp2_multiplication, + test_fp2_addition, + test_fp2_subtraction, + test_fp2_division, + test_fp2_random, + test_fp2_new +); +criterion_group!( + fp6_benches, + test_fp6_multiplication, + test_fp6_addition, + test_fp6_subtraction, + test_fp6_division, + test_fp6_random, + test_fp6_new +); +criterion_group!( + fp12_benches, + test_fp12_multiplication, + test_fp12_addition, + test_fp12_subtraction, + test_fp12_division, + test_fp12_random, + test_fp12_new +); + +criterion_main!( + g1_benches, + g2_benches, + fp_benches, + fp2_benches, + fp6_benches, + fp12_benches, + pairing_benches, + signature_benches +); diff --git a/benches/pairing.rs b/benches/pairing.rs new file mode 100644 index 0000000..167288b --- /dev/null +++ b/benches/pairing.rs @@ -0,0 +1,11 @@ +#![allow(dead_code)] +use criterion::{black_box, Criterion}; +use sylow::{pairing, G1Projective, G2Projective, GroupTrait}; + +pub fn test_pairing(c: &mut Criterion) { + let ga = G1Projective::generator(); + let gb = G2Projective::generator(); + c.bench_function("test_pairing", |b| { + b.iter(|| pairing(&black_box(ga), &black_box(gb))) + }); +} diff --git a/benches/sig.rs b/benches/sig.rs new file mode 100644 index 0000000..97ba53d --- /dev/null +++ b/benches/sig.rs @@ -0,0 +1,21 @@ +use criterion::{black_box, Criterion}; +use crypto_bigint::rand_core::OsRng; +use sha3::Keccak256; +use sylow::{FieldExtensionTrait, Fp, Fr, G1Projective, GroupTrait, XMDExpander}; + +const DST: &[u8; 30] = b"WARLOCK-CHAOS-V01-CS01-SHA-256"; +const MSG: &[u8; 4] = &20_i32.to_be_bytes(); +const K: u64 = 128; + +pub fn test_signing(c: &mut Criterion) { + let expander = XMDExpander::::new(DST, K); + let private_key = Fp::new(Fr::rand(&mut OsRng).value()); + + c.bench_function("test_signing", |b| { + b.iter(|| { + if let Ok(hashed_message) = G1Projective::hash_to_curve(&expander, MSG) { + let _signature = black_box(hashed_message) * black_box(private_key); + } + }) + }); +} diff --git a/examples/basic_pairing.rs b/examples/basic_pairing.rs new file mode 100644 index 0000000..8f80e3e --- /dev/null +++ b/examples/basic_pairing.rs @@ -0,0 +1,16 @@ +use sylow::{pairing, G1Projective, G2Projective, GroupTrait}; + +const RANGE: usize = 100; + +fn main() { + let a = G1Projective::generator(); + let b = G2Projective::generator(); + // let c = Fp::from(Fr::new_from_str("1901").unwrap().inv()); + // let d = Fp::from(Fr::new_from_str("2344").unwrap().inv()); + + for _ in 0..RANGE { + let _ = pairing(&a, &b); + // a = a * c; + // b = b * d; + } +} diff --git a/src/fields/extensions.rs b/src/fields/extensions.rs index 90881dc..22d2649 100644 --- a/src/fields/extensions.rs +++ b/src/fields/extensions.rs @@ -36,7 +36,7 @@ impl> FieldExtensio /// an extension need. /// # Arguments /// * `c` - a slice of field elements - pub(crate) const fn new(c: &[F; N]) -> Self { + pub const fn new(c: &[F; N]) -> Self { Self(*c) } /// There is eventually a need to be able to perform multiplication across different field diff --git a/src/fields/fp12.rs b/src/fields/fp12.rs index c3d42a8..19506bd 100644 --- a/src/fields/fp12.rs +++ b/src/fields/fp12.rs @@ -175,7 +175,8 @@ const FP12_QUADRATIC_NON_RESIDUE: Fp12 = Fp12::new(&[ ]), ]); -pub(crate) type Fp12 = FieldExtension<12, 2, Fp6>; +/// type alias for dodectic extension in the representation a + bw for a,b\in Fp6 +pub type Fp12 = FieldExtension<12, 2, Fp6>; impl FieldExtensionTrait<12, 2> for Fp12 { fn quadratic_non_residue() -> Self { diff --git a/src/fields/fp2.rs b/src/fields/fp2.rs index d7c1acb..1c5c2f5 100644 --- a/src/fields/fp2.rs +++ b/src/fields/fp2.rs @@ -45,6 +45,7 @@ const FP2_TWIST_CURVE_CONSTANT: Fp2 = Fp2::new(&[ 42524369107353300, ])), ]); +/// type alias for the quadratic extension of the base field pub type Fp2 = FieldExtension<2, 2, Fp>; // there are some specific things that must be defined as diff --git a/src/fields/fp6.rs b/src/fields/fp6.rs index 7da0f74..40d5997 100644 --- a/src/fields/fp6.rs +++ b/src/fields/fp6.rs @@ -170,8 +170,8 @@ const FP6_QUADRATIC_NON_RESIDUE: Fp6 = Fp6::new(&[ Fp2::new(&[Fp::ONE, Fp::ZERO]), Fp2::new(&[Fp::ZERO, Fp::ZERO]), ]); - -pub(crate) type Fp6 = FieldExtension<6, 3, Fp2>; +/// type alias for the sextic extension of the base field +pub type Fp6 = FieldExtension<6, 3, Fp2>; impl Fp6 { pub(crate) fn residue_mul(&self) -> Self { diff --git a/src/fields/mod.rs b/src/fields/mod.rs index 894228a..db1a279 100644 --- a/src/fields/mod.rs +++ b/src/fields/mod.rs @@ -3,4 +3,3 @@ pub(crate) mod fp; pub(crate) mod fp12; pub(crate) mod fp2; pub(crate) mod fp6; -pub(crate) mod utils; diff --git a/src/groups/g1.rs b/src/groups/g1.rs index 77a43ec..6fd9b79 100644 --- a/src/groups/g1.rs +++ b/src/groups/g1.rs @@ -13,9 +13,10 @@ use crate::fields::fp::{FieldExtensionTrait, Fp}; use crate::groups::group::{GroupAffine, GroupError, GroupProjective, GroupTrait}; use crate::hasher::Expander; -use crate::svdw::{SvdW, SvdWTrait}; +use crate::svdw::{MapError, SvdW, SvdWTrait}; use crypto_bigint::rand_core::CryptoRngCore; use num_traits::Zero; +use std::sync::OnceLock; use subtle::{Choice, ConstantTimeEq}; /// type alias for affine representation on base field @@ -23,6 +24,15 @@ pub type G1Affine = GroupAffine<1, 1, Fp>; /// type alias for projective representation on base field pub type G1Projective = GroupProjective<1, 1, Fp>; +/// this just creates a static instance of the SvdW map for G1 +static BN254_SVDW: OnceLock> = OnceLock::new(); + +/// This function returns the SvdW map for G1 on BN254 +pub fn get_bn254_svdw() -> Result<&'static SvdW, &'static MapError> { + BN254_SVDW + .get_or_init(|| SvdW::precompute_constants(Fp::ZERO, Fp::THREE)) + .as_ref() +} impl GroupTrait<1, 1, Fp> for G1Affine { fn generator() -> Self { Self { @@ -123,7 +133,7 @@ impl GroupTrait<1, 1, Fp> for G1Projective { let scalars = exp .hash_to_field(msg, COUNT, L) .expect("Hashing to base field failed"); - match SvdW::precompute_constants(Fp::from(0), Fp::from(3)) { + match get_bn254_svdw() { Ok(bn254_g1_svdw) => { let a = G1Projective::from( bn254_g1_svdw @@ -164,7 +174,7 @@ impl G1Projective { /// # Arguments /// * `v` - a tuple of field elements that represent the x, y, and z coordinates of the point #[allow(dead_code)] - pub(crate) fn new(v: [Fp; 3]) -> Result { + pub fn new(v: [Fp; 3]) -> Result { let _g1projective_is_on_curve = |x: &Fp, y: &Fp, z: &Fp| -> Choice { let y2 = y.square(); let x2 = x.square(); diff --git a/src/groups/g2.rs b/src/groups/g2.rs index a833e28..a3145a9 100644 --- a/src/groups/g2.rs +++ b/src/groups/g2.rs @@ -243,7 +243,7 @@ impl G2Projective { /// /// # Arguments /// * `v` - a tuple of field elements that represent the x, y, and z coordinates of the point - pub(crate) fn new(v: [Fp2; 3]) -> Result { + pub fn new(v: [Fp2; 3]) -> Result { let _g2projective_is_on_curve = |x: &Fp2, y: &Fp2, z: &Fp2| -> Choice { let y2 = y.square(); let x2 = x.square(); diff --git a/src/groups/mod.rs b/src/groups/mod.rs index 1ec0bba..93dabb9 100644 --- a/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -412,9 +412,10 @@ mod tests { } mod hash_tests { use super::*; + use crate::groups::g1::get_bn254_svdw; use crate::groups::group::GroupTrait; use crate::hasher::XMDExpander; - use crate::svdw::{SvdW, SvdWTrait}; + use crate::svdw::SvdWTrait; use sha2::Sha256; const DST: &[u8; 30] = b"WARLOCK-CHAOS-V01-CS01-SHA-256"; @@ -451,10 +452,7 @@ mod tests { fn test_svdw() { let g1_points = &*G1_REFERENCE_DATA; - if let Ok(d) = SvdW::precompute_constants( - Fp::ZERO, - >::curve_constant(), - ) { + if let Ok(d) = get_bn254_svdw() { for s in g1_points.svdw.iter() { let r = s.i; let p = s.p; diff --git a/src/hasher.rs b/src/hasher.rs index f892d67..52f767d 100644 --- a/src/hasher.rs +++ b/src/hasher.rs @@ -3,7 +3,7 @@ // //! and convert it into an element in the base field. use crate::fields::fp::Fp; -use crate::fields::utils::u256_to_u512; +use crate::utils::u256_to_u512; use crypto_bigint::{Encoding, NonZero, U256, U512}; use sha3::digest::crypto_common::BlockSizeUser; use sha3::digest::{ExtendableOutput, FixedOutput}; @@ -90,11 +90,12 @@ pub trait Expander { } } -pub(crate) struct XMDExpander { - /// This implements the XMD function, which produces a uniformly random - /// byte string using a hash function that outputs b bits. - /// Usage of this function is recommended only with Sha2 and Sha3 hashes. - /// +/// This implements the XMD function, which produces a uniformly random +/// byte string using a hash function that outputs b bits. +/// Usage of this function is recommended only with Sha2 and Sha3 hashes. +/// +#[derive(Debug)] +pub struct XMDExpander { dst_prime: Vec, hash_fn: std::marker::PhantomData, security_param: u64, @@ -107,7 +108,7 @@ impl XMDExpander { /// # Arguments /// * `dst` - the domain separation tag /// * `security_param` - the desired bit level of security - pub(crate) fn new(dst: &[u8], security_param: u64) -> Self { + pub fn new(dst: &[u8], security_param: u64) -> Self { let dst_prime = if dst.len() > 255 { let mut hasher = D::default(); hasher.update(Self::OVERSIZE_DST_PREFIX); @@ -175,11 +176,12 @@ impl Expander for XMDExpander { } } -struct XOFExpander { - /// This implements the XOF function, which produces a uniformly random - /// byte string using an extendable output function (XOF) H. In this instance, - /// the Shake XOF family are the only recommended choices. - /// +/// This implements the XOF function, which produces a uniformly random +/// byte string using an extendable output function (XOF) H. In this instance, +/// the Shake XOF family are the only recommended choices. +/// +#[derive(Debug)] +pub struct XOFExpander { dst_prime: Vec, hash_fn: std::marker::PhantomData, } diff --git a/src/lib.rs b/src/lib.rs index e83b105..6dd2f64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,13 +19,19 @@ mod groups; mod hasher; mod pairing; mod svdw; +pub(crate) mod utils; pub use crate::fields::fp::{FieldExtensionTrait, Fp, Fr}; pub use crate::groups::g1::{G1Affine, G1Projective}; -pub use crate::groups::g2::G2Projective; +pub use crate::groups::g2::{G2Affine, G2Projective}; pub use crate::groups::group::{GroupError, GroupTrait}; pub use crate::groups::gt::Gt; -use crate::hasher::XMDExpander; + +pub use crate::fields::fp12::Fp12; +pub use crate::fields::fp2::Fp2; +pub use crate::fields::fp6::Fp6; + +pub use crate::hasher::{XMDExpander, XOFExpander}; pub use crate::pairing::{glued_miller_loop, pairing, G2PreComputed}; use crypto_bigint::rand_core::OsRng; use sha3::Keccak256; diff --git a/src/fields/utils.rs b/src/utils.rs similarity index 100% rename from src/fields/utils.rs rename to src/utils.rs diff --git a/sylow.png b/sylow.png index 5b589b6..f0ce9c3 100644 Binary files a/sylow.png and b/sylow.png differ