2017-12-18 11:00:10 -07:00
|
|
|
use jubjub::*;
|
|
|
|
use pairing::*;
|
2018-03-05 17:58:34 -07:00
|
|
|
use blake2_rfc::blake2s::Blake2s;
|
2017-12-18 11:00:10 -07:00
|
|
|
|
2018-03-05 18:08:49 -07:00
|
|
|
/// This is chosen to be some random string that we couldn't have anticipated when we designed
|
|
|
|
/// the algorithm, for rigidity purposes.
|
|
|
|
pub const FIRST_BLOCK: &'static [u8; 64] = b"0000000000000000002ffe76b973aabaff1d1557d79acf2c3795809c83caf580";
|
|
|
|
|
2017-12-18 11:00:10 -07:00
|
|
|
/// 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],
|
2018-03-05 19:21:41 -07:00
|
|
|
personalization: &[u8],
|
2017-12-18 11:00:10 -07:00
|
|
|
params: &E::Params
|
2018-01-29 08:56:58 -07:00
|
|
|
) -> Option<edwards::Point<E, PrimeOrder>>
|
2017-12-18 11:00:10 -07:00
|
|
|
{
|
2018-03-05 19:21:41 -07:00
|
|
|
assert_eq!(personalization.len(), 8);
|
|
|
|
|
2017-12-18 11:00:10 -07:00
|
|
|
// Check to see that scalar field is 255 bits
|
|
|
|
assert!(E::Fr::NUM_BITS == 255);
|
|
|
|
|
2018-03-05 19:21:41 -07:00
|
|
|
let mut h = Blake2s::with_params(32, &[], &[], personalization);
|
2018-03-05 18:08:49 -07:00
|
|
|
h.update(FIRST_BLOCK);
|
2018-03-05 17:58:34 -07:00
|
|
|
h.update(tag);
|
|
|
|
let mut h = h.finalize().as_ref().to_vec();
|
2017-12-18 11:00:10 -07:00
|
|
|
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
|
2018-01-29 08:56:58 -07:00
|
|
|
let mut y0 = <E::Fr as PrimeField>::Repr::default();
|
|
|
|
y0.read_be(&h[..]).expect("hash is sufficiently large");
|
2017-12-18 11:00:10 -07:00
|
|
|
|
2018-01-29 08:56:58 -07:00
|
|
|
if let Ok(y0) = E::Fr::from_repr(y0) {
|
|
|
|
if let Some(p) = edwards::Point::<E, _>::get_for_y(y0, s, params) {
|
2017-12-18 11:00:10 -07:00
|
|
|
// Enter into the prime order subgroup
|
|
|
|
let p = p.mul_by_cofactor(params);
|
|
|
|
|
2018-01-29 08:56:58 -07:00
|
|
|
if p != edwards::Point::zero() {
|
2017-12-22 02:57:34 -07:00
|
|
|
Some(p)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2017-12-18 11:00:10 -07:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|