Sean Bowe
7 years ago
3 changed files with 45 additions and 31 deletions
@ -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<E: JubjubEngine>( |
||||||
|
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 = <E::Fr as PrimeField>::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::<E, _>::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 |
||||||
|
} |
||||||
|
} |
@ -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<E: JubjubEngine>(tag: &[u8], params: &E::Params) -> Option<montgomery::Point<E, PrimeOrder>> { |
|
||||||
// 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 = <E::Fr as PrimeField>::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 |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue