Introduce Curve::hasher abstraction.

This commit is contained in:
Sean Bowe 2021-02-02 11:36:06 -07:00 committed by Daira Hopwood
parent 68a7a19d3b
commit 83e2656c3e
4 changed files with 64 additions and 18 deletions

View file

@ -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<dyn Fn(&[u8]) -> 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;

View file

@ -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<dyn Fn(&[u8]) -> 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<dyn Fn(&[u8]) -> 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([

View file

@ -27,11 +27,11 @@ lazy_static! {
/// The iso-Pallas -> Pallas degree 3 isogeny map.
pub static ref MAP: SimplifiedSWUWithDegree3Isogeny<Base, Affine, IsoAffine> = {
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);

View file

@ -27,11 +27,11 @@ lazy_static! {
/// The iso-Vesta -> Vesta degree 3 isogeny map.
pub static ref MAP: SimplifiedSWUWithDegree3Isogeny<Base, Affine, IsoAffine> = {
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);