diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index e23151f..1d946d2 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -79,6 +79,12 @@ pub trait Curve: /// Return the Jacobian coordinates of this point. fn jacobian_coordinates(&self) -> (Self::Base, Self::Base, Self::Base); + /// Requests a hasher that accepts messages and returns near-uniformly + /// distributed elements in the group, given domain prefix `hasher`. + /// + /// This method is suitable for use as a random oracle. + fn hasher(domain_prefix: &str) -> Box Self + 'static>; + /// Returns whether or not this element is on the curve; should /// always be true unless an "unchecked" API was used. fn is_on_curve(&self) -> Choice; diff --git a/src/pasta/curves.rs b/src/pasta/curves.rs index c5a836c..8404faf 100644 --- a/src/pasta/curves.rs +++ b/src/pasta/curves.rs @@ -12,7 +12,7 @@ use super::{Fp, Fq}; use crate::arithmetic::{Curve, CurveAffine, FieldExt, Group}; macro_rules! new_curve_impl { - ($name:ident, $name_affine:ident, $base:ident, $scalar:ident, $blake2b_personalization:literal, + ($name:ident, $name_affine:ident, $iso_affine:ident, $base:ident, $scalar:ident, $blake2b_personalization:literal, $curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => { /// Represents a point in the projective coordinate space. #[derive(Copy, Clone, Debug)] @@ -56,7 +56,7 @@ macro_rules! new_curve_impl { type Scalar = $scalar; type Base = $base; - impl_projective_curve_specific!($name, $base, $curve_type); + impl_projective_curve_specific!($name, $name_affine, $iso_affine, $base, $curve_type); fn zero() -> Self { Self { @@ -685,7 +685,38 @@ macro_rules! new_curve_impl { } macro_rules! impl_projective_curve_specific { - ($name:ident, $base:ident, special_a0_b5) => { + ($name:ident, $name_affine:ident, $iso_affine:ident, $base:ident, special_a0_b5) => { + fn hasher(domain_prefix: &str) -> Box Self + 'static> { + use super::hashtocurve::SimplifiedSWUWithDegree3Isogeny; + + let swu: SimplifiedSWUWithDegree3Isogeny<$base, $name_affine, $iso_affine> = + SimplifiedSWUWithDegree3Isogeny::new( + $name::Z, + $name::ISOGENY_CONSTANTS, + $name::MINUS_B_OVER_A, + $name::B_OVER_ZA, + $name::THETA, + ); + + let domain_separation_tag: String = format!( + "{}-{}_{}_{}_RO_", + domain_prefix, + $name_affine::CURVE_ID, + "XOF:SHAKE128", + "SSWU" + ); + + Box::new(move |message| { + let mut us = [Field::zero(); 2]; + SimplifiedSWUWithDegree3Isogeny::<$base, $name_affine, $iso_affine>::hash_to_field( + message, + domain_separation_tag.as_bytes(), + &mut us, + ); + swu.field_elements_to_curve(&us[0], &us[1]) + }) + } + fn one() -> Self { // NOTE: This is specific to b = 5 @@ -740,7 +771,12 @@ macro_rules! impl_projective_curve_specific { $name::conditional_select(&tmp, &$name::zero(), self.is_zero()) } }; - ($name:ident, $base:ident, general) => { + ($name:ident, $name_affine:ident, $iso_affine:ident, $base:ident, general) => { + /// Unimplemented: hashing to this curve is not supported + fn hasher(_domain_prefix: &str) -> Box Self + 'static> { + unimplemented!() + } + /// Unimplemented: there is no standard generator for this curve. fn one() -> Self { unimplemented!() @@ -807,6 +843,7 @@ macro_rules! impl_affine_curve_specific { new_curve_impl!( Ep, EpAffine, + IsoEpAffine, Fp, Fq, b"halo2_____pallas", @@ -818,6 +855,7 @@ new_curve_impl!( new_curve_impl!( Eq, EqAffine, + IsoEqAffine, Fq, Fp, b"halo2______vesta", @@ -829,6 +867,7 @@ new_curve_impl!( new_curve_impl!( IsoEp, IsoEpAffine, + EpAffine, Fp, Fq, b"halo2_iso_pallas", @@ -845,6 +884,7 @@ new_curve_impl!( new_curve_impl!( IsoEq, IsoEqAffine, + EqAffine, Fq, Fp, b"halo2__iso_vesta", @@ -859,7 +899,7 @@ new_curve_impl!( general ); -impl IsoEpAffine { +impl Ep { /// Constants used for computing the isogeny from IsoEp to Ep. pub const ISOGENY_CONSTANTS: [Fp; 13] = [ Fp::from_raw([ @@ -977,7 +1017,7 @@ impl IsoEpAffine { ]); } -impl IsoEqAffine { +impl Eq { /// Constants used for computing the isogeny from IsoEq to Eq. pub const ISOGENY_CONSTANTS: [Fq; 13] = [ Fq::from_raw([ diff --git a/src/pasta/pallas.rs b/src/pasta/pallas.rs index 5e0da73..a52dd37 100644 --- a/src/pasta/pallas.rs +++ b/src/pasta/pallas.rs @@ -27,11 +27,11 @@ lazy_static! { /// The iso-Pallas -> Pallas degree 3 isogeny map. pub static ref MAP: SimplifiedSWUWithDegree3Isogeny = { SimplifiedSWUWithDegree3Isogeny::new( - IsoAffine::Z, - IsoAffine::ISOGENY_CONSTANTS, - IsoAffine::MINUS_B_OVER_A, - IsoAffine::B_OVER_ZA, - IsoAffine::THETA + Point::Z, + Point::ISOGENY_CONSTANTS, + Point::MINUS_B_OVER_A, + Point::B_OVER_ZA, + Point::THETA ) }; } @@ -90,7 +90,7 @@ fn test_map_to_curve_pallas() { .collect(); assert!(set.len() == 10000); - let hash = MAP.hash_to_curve("z.cash:test"); + let hash = Point::hasher("z.cash:test"); let p: Point = hash(b"hello"); let (x, y, z) = p.jacobian_coordinates(); println!("{:?}", p); diff --git a/src/pasta/vesta.rs b/src/pasta/vesta.rs index 8dac763..4003542 100644 --- a/src/pasta/vesta.rs +++ b/src/pasta/vesta.rs @@ -27,11 +27,11 @@ lazy_static! { /// The iso-Vesta -> Vesta degree 3 isogeny map. pub static ref MAP: SimplifiedSWUWithDegree3Isogeny = { SimplifiedSWUWithDegree3Isogeny::new( - IsoAffine::Z, - IsoAffine::ISOGENY_CONSTANTS, - IsoAffine::MINUS_B_OVER_A, - IsoAffine::B_OVER_ZA, - IsoAffine::THETA + Point::Z, + Point::ISOGENY_CONSTANTS, + Point::MINUS_B_OVER_A, + Point::B_OVER_ZA, + Point::THETA ) }; } @@ -50,7 +50,7 @@ fn test_map_to_curve_vesta() { .collect(); assert!(set.len() == 10000); - let hash = MAP.hash_to_curve("z.cash:test"); + let hash = Point::hasher("z.cash:test"); let p: Point = hash(b"hello"); let (x, y, z) = p.jacobian_coordinates(); println!("{:?}", p);