() {
- let data = vec![1u8, 2, 3, 4, 5];
- let _g1 =
- ::hash_to_group::<&[u8]>(data.as_ref(), "bls signature".as_ref())
- .unwrap();
- }
-}
+pub use short_weierstrass::SWHashToGroup;
+pub use twisted_edwards::TEHashToGroup;
diff --git a/primitives/src/hash_to_group/short_weierstrass.rs b/primitives/src/hash_to_group/short_weierstrass.rs
new file mode 100644
index 000000000..20f75a0cf
--- /dev/null
+++ b/primitives/src/hash_to_group/short_weierstrass.rs
@@ -0,0 +1,81 @@
+// Copyright (c) 2022 Espresso Systems (espressosys.com)
+// This file is part of the Jellyfish library.
+
+// You should have received a copy of the MIT License
+// along with the Jellyfish library. If not, see .
+
+//! Hash to Elliptic Curve implementation of
+
+use crate::errors::PrimitivesError;
+use ark_ec::{
+ short_weierstrass_jacobian::{GroupAffine, GroupProjective},
+ AffineCurve, SWModelParameters,
+};
+use ark_std::{
+ rand::{Rng, SeedableRng},
+ UniformRand,
+};
+use digest::Digest;
+use rand_chacha::ChaCha20Rng;
+use sha2::Sha256;
+
+/// Trait definition and default implementation for hash to group functions for
+/// Short Weierstrass Curves.
+pub trait SWHashToGroup: SWModelParameters + Sized {
+ /// Hash to Group point, using sha2-512 function
+ /// hashing to G1 point of `C: ProjectiveCurve`.
+ // Default implementation implements a naive solution via rejection sampling.
+ // Slow, and non-constant time.
+ //
+ // For specific curves we may want to overload it with a more efficient
+ // algorithm, such as IETF BLS draft.
+ fn hash_to_group>(
+ data: B,
+ cs_id: B,
+ ) -> Result, PrimitivesError> {
+ let mut hasher = Sha256::new();
+ hasher.update([cs_id.as_ref(), data.as_ref()].concat());
+ let mut seed = [0u8; 32];
+ seed.copy_from_slice(hasher.finalize().as_ref());
+ let mut rng = ChaCha20Rng::from_seed(seed);
+ loop {
+ let x = Self::BaseField::rand(&mut rng);
+ // a boolean flag to decide if y is positive or not
+ let y_flag = rng.gen();
+ if let Some(p) = GroupAffine::::get_point_from_x(x, y_flag) {
+ return Ok(p.mul_by_cofactor_to_projective());
+ }
+ }
+ }
+}
+
+impl SWHashToGroup for ark_bls12_381::g1::Parameters {
+ // TODO:
+ // overload hash to group with the method in
+ //
+}
+
+impl SWHashToGroup for ark_bls12_377::g1::Parameters {
+ // TODO:
+ // overload hash to group with the method in
+ //
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use ark_std::vec;
+
+ #[test]
+ fn test_hash_to_group() {
+ test_hash_to_group_helper::();
+ test_hash_to_group_helper::();
+ }
+
+ fn test_hash_to_group_helper() {
+ let data = vec![1u8, 2, 3, 4, 5];
+ let _g1 =
+ ::hash_to_group::<&[u8]>(data.as_ref(), "bls signature".as_ref())
+ .unwrap();
+ }
+}
diff --git a/primitives/src/hash_to_group/twisted_edwards.rs b/primitives/src/hash_to_group/twisted_edwards.rs
new file mode 100644
index 000000000..09b32c589
--- /dev/null
+++ b/primitives/src/hash_to_group/twisted_edwards.rs
@@ -0,0 +1,81 @@
+// Copyright (c) 2022 Espresso Systems (espressosys.com)
+// This file is part of the Jellyfish library.
+
+// You should have received a copy of the MIT License
+// along with the Jellyfish library. If not, see .
+
+//! Hash to Elliptic Curve implementation of
+
+use crate::errors::PrimitivesError;
+use ark_ec::{
+ twisted_edwards_extended::{GroupAffine, GroupProjective},
+ AffineCurve, TEModelParameters,
+};
+use ark_std::{
+ rand::{Rng, SeedableRng},
+ UniformRand,
+};
+use digest::Digest;
+use rand_chacha::ChaCha20Rng;
+use sha2::Sha256;
+
+/// Trait definition and default implementation for hash to group functions for
+/// Twisted Edwards Curves.
+pub trait TEHashToGroup: TEModelParameters + Sized {
+ /// Hash to Group point, using sha2-512 function
+ /// hashing to G1 point of `C: ProjectiveCurve`.
+ // Default implementation implements a naive solution via rejection sampling.
+ // Slow, and non-constant time.
+ //
+ // For specific curves we may want to overload it with a more efficient
+ // algorithm, such as IETF BLS draft.
+ fn hash_to_group>(
+ data: B,
+ cs_id: B,
+ ) -> Result, PrimitivesError> {
+ let mut hasher = Sha256::new();
+ hasher.update([cs_id.as_ref(), data.as_ref()].concat());
+ let mut seed = [0u8; 32];
+ seed.copy_from_slice(hasher.finalize().as_ref());
+ let mut rng = ChaCha20Rng::from_seed(seed);
+ loop {
+ let x = Self::BaseField::rand(&mut rng);
+ // a boolean flag to decide if y is positive or not
+ let y_flag = rng.gen();
+ if let Some(p) = GroupAffine::::get_point_from_x(x, y_flag) {
+ return Ok(p.mul_by_cofactor_to_projective());
+ }
+ }
+ }
+}
+
+impl TEHashToGroup for ark_ed_on_bls12_377::EdwardsParameters {
+ // TODO:
+ // overload hash to group with the method in
+ //
+}
+
+impl TEHashToGroup for ark_ed_on_bls12_381::EdwardsParameters {
+ // TODO:
+ // overload hash to group with the method in
+ //
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use ark_std::vec;
+
+ #[test]
+ fn test_hash_to_group() {
+ test_hash_to_group_helper::();
+ test_hash_to_group_helper::();
+ }
+
+ fn test_hash_to_group_helper() {
+ let data = vec![1u8, 2, 3, 4, 5];
+ let _g1 =
+ ::hash_to_group::<&[u8]>(data.as_ref(), "Jubjub curves".as_ref())
+ .unwrap();
+ }
+}
diff --git a/primitives/src/signatures/bls.rs b/primitives/src/signatures/bls.rs
index ce3bd801b..5fda9b4f8 100644
--- a/primitives/src/signatures/bls.rs
+++ b/primitives/src/signatures/bls.rs
@@ -1,7 +1,9 @@
//! Placeholder for BLS signature.
use super::SignatureScheme;
-use crate::{constants::CS_ID_BLS_SIG_NAIVE, errors::PrimitivesError, hash_to_group::HashToGroup};
+use crate::{
+ constants::CS_ID_BLS_SIG_NAIVE, errors::PrimitivesError, hash_to_group::SWHashToGroup,
+};
use ark_ec::{
bls12::{Bls12, Bls12Parameters},
short_weierstrass_jacobian::GroupAffine,
@@ -51,7 +53,7 @@ pub struct BLSSignature(pub(crate) GroupAffine SignatureScheme for BLSSignatureScheme
where
P: Bls12Parameters,
- P::G1Parameters: HashToGroup,
+ P::G1Parameters: SWHashToGroup,
{
const CS_ID: &'static str = CS_ID_BLS_SIG_NAIVE;
@@ -105,7 +107,7 @@ where
msg: M,
_prng: &mut R,
) -> Result {
- let hm = ::hash_to_group(
+ let hm = ::hash_to_group(
msg.as_ref(),
CS_ID_BLS_SIG_NAIVE.as_ref(),
)?;
@@ -119,7 +121,7 @@ where
msg: M,
sig: &Self::Signature,
) -> Result<(), PrimitivesError> {
- let hm = ::hash_to_group(
+ let hm = ::hash_to_group(
msg.as_ref(),
CS_ID_BLS_SIG_NAIVE.as_ref(),
)?;
diff --git a/primitives/src/vrf/blsvrf.rs b/primitives/src/vrf/blsvrf.rs
index 500810f1a..04c7ed2ef 100644
--- a/primitives/src/vrf/blsvrf.rs
+++ b/primitives/src/vrf/blsvrf.rs
@@ -4,7 +4,7 @@ use super::Vrf;
use crate::{
constants::CS_ID_BLS_VRF_NAIVE,
errors::PrimitivesError,
- hash_to_group::HashToGroup,
+ hash_to_group::SWHashToGroup,
signatures::{
bls::{BLSSignKey, BLSSignature, BLSVerKey},
BLSSignatureScheme, SignatureScheme,
@@ -29,7 +29,7 @@ impl Vrf for BLSVRFScheme
where
H: Digest,
P: Bls12Parameters,
- P::G1Parameters: HashToGroup,
+ P::G1Parameters: SWHashToGroup,
{
const CS_ID: &'static str = CS_ID_BLS_VRF_NAIVE;