diff --git a/src/group_hash.rs b/src/group_hash.rs new file mode 100644 index 0000000..cc6ed4a --- /dev/null +++ b/src/group_hash.rs @@ -0,0 +1,44 @@ +use jubjub::*; +use pairing::*; +use blake2::{Blake2s}; +use digest::{FixedOutput, Input}; + +/// Produces an (x, y) pair (Montgomery) for a +/// random point in the Jubjub curve. The point +/// is guaranteed to be prime order and not the +/// identity. +pub fn group_hash( + tag: &[u8], + params: &E::Params +) -> Option<(E::Fr, E::Fr)> +{ + // Check to see that scalar field is 255 bits + assert!(E::Fr::NUM_BITS == 255); + + // TODO: personalization/first block + let mut h = Blake2s::new_keyed(&[], 32); + h.process(tag); + let mut h = h.fixed_result().to_vec(); + assert!(h.len() == 32); + + // Take first/unset first bit of hash + let s = h[0] >> 7 == 1; // get s + h[0] &= 0b0111_1111; // unset s from h + + // cast to prime field representation + let mut x0 = ::Repr::default(); + x0.read_be(&h[..]).expect("hash is sufficiently large"); + + if let Ok(x0) = E::Fr::from_repr(x0) { + if let Some(p) = montgomery::Point::::get_for_x(x0, s, params) { + // Enter into the prime order subgroup + let p = p.mul_by_cofactor(params); + + p.into_xy() + } else { + None + } + } else { + None + } +} diff --git a/src/grouphash/mod.rs b/src/grouphash/mod.rs deleted file mode 100644 index 8e69916..0000000 --- a/src/grouphash/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -// 64 zeros, substitute with random future determined string like a blockhash, or randomness beacom -const U: [u8; 64] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - -// option to return None or point -fn grouphash(tag: &[u8], params: &E::Params) -> Option> { - // Check to see that scalar field is 255 bits - assert! (E::Fr::NUM_BITS == 255); - - // Perform hash, get random 32-byte string - let mut h = Blake2s::new_keyed(&[], 32); - h.process(&U); - h.process(tag); - let h = h.fixed_result(); - - // Take first unset first bit of hash - let sign = (h[0] >> 7) == 1; - h[0] &= 0b01111111; - - // cast to prime field representation - let mut x0 = ::Repr::default(); - x0.read_be(&h[..]).unwrap(); - - match E::Fr::from_repr(x0) { - Ok(x0) => { - let tmp = montgomery::Point::get_for_x(x0, sign, params).mul_by_cofactor(params); - if tmp == mongomery::Point.zero() { None } else { Some(tmp) }; - } - Err(_) => None - } -} diff --git a/src/lib.rs b/src/lib.rs index efce841..8dbcb47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,4 @@ extern crate rand; pub mod jubjub; pub mod circuit; -pub mod grouphash; +pub mod group_hash;