Skip to content

Commit

Permalink
add hash to curve suite
Browse files Browse the repository at this point in the history
  • Loading branch information
kilic committed Mar 26, 2024
1 parent dc57ddd commit a738da4
Show file tree
Hide file tree
Showing 24 changed files with 788 additions and 734 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ hex = { version = "0.4", optional = true, default-features = false, features = [
blake2b_simd = "1"
rayon = "1.8"
unroll = "0.1.5"
blake2 = "0.10.6"
sha2 = "0.10.8"
digest = "0.10.7"

[features]
default = ["bits"]
Expand Down
34 changes: 31 additions & 3 deletions src/bn256/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::Curve;
use crate::group::{cofactor::CofactorGroup, prime::PrimeCurveAffine, Group, GroupEncoding};
use crate::hash_to_curve::svdw_hash_to_curve;
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,
Expand Down Expand Up @@ -39,7 +38,7 @@ new_curve_impl!(
G1_A,
G1_B,
"bn256_g1",
|curve_id, domain_prefix| svdw_hash_to_curve(curve_id, domain_prefix, G1::SVDW_Z),
|domain_prefix| crate::hash_to_curve::hash_to_curve(domain_prefix, G1::default_hash_to_curve_suite()),
);

new_curve_impl!(
Expand All @@ -53,9 +52,18 @@ new_curve_impl!(
G2_A,
G2_B,
"bn256_g2",
|_, _| unimplemented!(),
|domain_prefix| hash_to_curve_g2(domain_prefix),
);

#[allow(clippy::type_complexity)]
pub(crate) fn hash_to_curve_g2<'a>(domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> G2 + 'a> {
let suite = G2::default_hash_to_curve_suite();
Box::new(move |message| {
let r0 = suite.hash_to_curve(domain_prefix, message);
r0.clear_cofactor()
})
}

const G1_GENERATOR_X: Fq = Fq::one();
const G1_GENERATOR_Y: Fq = Fq::from_raw([2, 0, 0, 0]);
const G1_A: Fq = Fq::from_raw([0, 0, 0, 0]);
Expand Down Expand Up @@ -196,6 +204,26 @@ impl CofactorGroup for G2 {

impl G1 {
const SVDW_Z: Fq = Fq::ONE;

fn default_hash_to_curve_suite() -> crate::hash_to_curve::Suite<Self, sha2::Sha256, 64> {
crate::hash_to_curve::Suite::<G1, sha2::Sha256, 64>::new(
b"bn256_g1_XMD:SHA-256_SVDW_RO_",
Self::SVDW_Z,
crate::hash_to_curve::Method::SVDW,
)
}
}

impl G2 {
const SVDW_Z: Fq2 = Fq2::ONE;

fn default_hash_to_curve_suite() -> crate::hash_to_curve::Suite<Self, sha2::Sha256, 128> {
crate::hash_to_curve::Suite::<G2, sha2::Sha256, 128>::new(
b"bn256_g2_XMD:SHA-256_SVDW_RO_",
Self::SVDW_Z,
crate::hash_to_curve::Method::SVDW,
)
}
}

#[cfg(test)]
Expand Down
67 changes: 1 addition & 66 deletions src/bn256/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,70 +294,5 @@ mod test {
crate::field_testing_suite!(Fq, "constants", MODULUS_STR);
crate::field_testing_suite!(Fq, "sqrt");
crate::field_testing_suite!(Fq, "zeta");
crate::field_testing_suite!(
Fq,
"from_uniform_bytes",
[
Fq::from_raw([
0xd1f334151139642a,
0xb0f28bcaa90fdb88,
0x9a13255d88eca613,
0x02afef300dd32d9a,
]),
Fq::from_raw([
0x03cd906680808fbe,
0xc28902db5aef5254,
0x3dbdb406ae292ddf,
0x276ec249e6b9e195
]),
Fq::from_raw([
0xb0e07ded189e91f7,
0x9e3b0caae2b98899,
0x49e511f19341fdcf,
0x1ea71260f64b72da
]),
Fq::from_raw([
0x61132be14bb978d4,
0xe27e09a20808067b,
0x3842cc8fd1d8406f,
0x13163c8a13fd550b
]),
Fq::from_raw([
0x04a6495a33d39ac5,
0xc918e75bb383fae0,
0x80068784d577b035,
0x1dd962b86e44e1be
]),
Fq::from_raw([
0x107ffeecf4cb3348,
0x53a0adb5491a4944,
0x50028f636ffcb780,
0x0af7f3aa38015c1d
]),
Fq::from_raw([
0x22513787342eba07,
0x4fac22ed88770319,
0x0b7c31082cc92b13,
0x250e22a8cac6e790
]),
Fq::from_raw([
0x5954fd7dda014940,
0x9df859b2124e66fa,
0xaab48d94eadd9d14,
0x2a9a75013e3da632
]),
Fq::from_raw([
0xedd59c88fee718de,
0x2b034dcfe6de3844,
0x76b0e2e360488694,
0x068998ef20d62df1
]),
Fq::from_raw([
0xac161667911634a4,
0x296c2f453152552f,
0x2653625dfaa1cf74,
0x171abf201a2587d7
]),
]
);
crate::field_testing_suite!(Fq, "from_uniform_bytes", 64);
}
9 changes: 9 additions & 0 deletions src/bn256/fq2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,15 @@ impl FromUniformBytes<64> for Fq2 {
Self::new(Fq::from_uniform_bytes(bytes), Fq::zero())
}
}

impl FromUniformBytes<128> for Fq2 {
fn from_uniform_bytes(bytes: &[u8; 128]) -> Self {
let c0 = bytes[..64].try_into().unwrap();
let c1 = bytes[64..].try_into().unwrap();
Self::new(Fq::from_uniform_bytes(c0), Fq::from_uniform_bytes(c1))
}
}

#[derive(Clone, Copy, Debug)]
pub struct Fq2Bytes([u8; 64]);

Expand Down
68 changes: 2 additions & 66 deletions src/bn256/fr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ impl WithSmallOrderMulGroup<3> for Fr {

#[cfg(test)]
mod test {

use super::*;
crate::field_testing_suite!(Fr, "field_arithmetic");
crate::field_testing_suite!(Fr, "conversion");
Expand All @@ -342,72 +343,7 @@ mod test {
crate::field_testing_suite!(Fr, "constants", MODULUS_STR);
crate::field_testing_suite!(Fr, "sqrt");
crate::field_testing_suite!(Fr, "zeta");
crate::field_testing_suite!(
Fr,
"from_uniform_bytes",
[
Fr::from_raw([
0x2ca6366467811a07,
0x22727e3db430ed7e,
0xbdb79bcb97d9e250,
0x2cee6d1152d1d7b0
]),
Fr::from_raw([
0x6ec33f1a3af8cb2d,
0x2c8f3330e85dab4b,
0xfeeff4ae1b019172,
0x095cd2a455dd67b6
]),
Fr::from_raw([
0x4741eee9c02c9f33,
0xfc0111dd8aeb7e7a,
0xb1d79e2a22d4ab08,
0x0cb7168893a7bbda
]),
Fr::from_raw([
0xc2ff8410555287f8,
0x0927fbea8c6049c8,
0xc0edccc8e4d3efe4,
0x1d724b76911436c4
]),
Fr::from_raw([
0xdef98bc8d4db6e5b,
0x42f0ea50590d557e,
0x1f311a3b8114fd9a,
0x0487c555645c67b1
]),
Fr::from_raw([
0x8ad4879b05ceb610,
0x2e4e9a46537c84b0,
0x5cfa7c43c9dfcfa1,
0x0b6b2a4d122d0bb6
]),
Fr::from_raw([
0xe7f11ee016df7fe7,
0x6419da89bd8aef3d,
0x3511f5d293af95c8,
0x10379c1d4d49593a
]),
Fr::from_raw([
0xd63080c8aa3ecd37,
0x19c20f30b56fe458,
0xc9dbbcb3aa780e06,
0x28a4e2b8273762c6
]),
Fr::from_raw([
0xecea51b521eac0b8,
0x65fff58a5881c562,
0x603ac7d1e06ef3af,
0x1e0c2c51226eecea
]),
Fr::from_raw([
0xe6ec4779b8bd6516,
0x0d5411f3cb9504ae,
0xff706ec73df8e92a,
0x2c56d60b3e351e56
]),
]
);
crate::field_testing_suite!(Fr, "from_uniform_bytes", 64);

#[test]
fn bench_fr_from_u16() {
Expand Down
50 changes: 0 additions & 50 deletions src/bn256/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,3 @@ pub use fq12::*;
pub use fq2::*;
pub use fq6::*;
pub use fr::*;

#[cfg(test)]
mod test {
use super::G1 as Bn256Point;
use group::GroupEncoding;
use pasta_curves::arithmetic::CurveExt;
use rand_core::{RngCore, SeedableRng};

#[test]
fn test_consistent_hash_to_curve() {
// The goal of this test is to generate test vectors to ensure that the ASM implementation
// matches the rust implementation.
let num_vecs = 10;

// Test vectors generated with rust implementation.
let expected_results = [
"e0c5a6834e0329b4f8bdc91144b3e687ac9d810a8e899415267db9cfbf61e91e",
"7052a20bee99cbe054fdd8b2e336db3ed3e9a265229e44ab8197c5eabdef2b0b",
"2f058acc133957074ac79e9b9b1867a0cf3d13df7aa7de7f48e9a6be7d96aa6d",
"b2ff44a25693b811f35e33feb3e99ad9ba0d06425a3ffd5e79cef63d20143314",
"ab2f6d71d2fde51546d8a5782aa9f707e585b84644470f0c876784dbebd30c55",
"6a4e0e30f37a8d1b92b8cf08df3735a36b4937ee455a9dc5f9283a13530db144",
"f1c69be8c5f5f9e28b0e9f76ab77651a7dcaaae371fbba66450cbcee0ed5b16b",
"e86267c2e3355d7a6f664a0ea71374406337d452a3f9a294a0594df53c08df21",
"03cf55ca983ecd8a2e2baae18d979d97d688a978d829701c66a14d7c4da58e62",
"5302c2cfe3c909e9378d08c951bb33d0813818a1baf734379aac8aaa47f38f0d",
];

let mut seeded_rng = rand_chacha::ChaChaRng::seed_from_u64(0u64);
let uniform_bytes = std::iter::from_fn(|| {
let mut bytes = [0u8; 32];
seeded_rng.fill_bytes(&mut bytes);
Some(bytes)
})
.take(num_vecs)
.collect::<Vec<_>>();
let hash = Bn256Point::hash_to_curve("from_uniform_bytes");
for i in 0..num_vecs {
let p = hash(&uniform_bytes[i]);
let expected_result = hex::decode(expected_results[i]).unwrap();
assert_eq!(
p.to_bytes().as_ref(),
&expected_result[..],
"hash_to_curve_print failed, expected: {}, got: {}",
expected_results[i],
hex::encode(p.to_bytes().as_ref())
);
}
}
}
2 changes: 1 addition & 1 deletion src/derive/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ macro_rules! new_curve_impl {

#[allow(clippy::redundant_closure_call)]
fn hash_to_curve<'a>(domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
$hash_to_curve($curve_id, domain_prefix)
$hash_to_curve(domain_prefix)
}

fn is_on_curve(&self) -> Choice {
Expand Down
Loading

0 comments on commit a738da4

Please sign in to comment.