Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elliptic-curve: CofactorGroup requirement for hash2curve implementation #1146

Open
andrewwhitehead opened this issue Oct 31, 2022 · 3 comments

Comments

@andrewwhitehead
Copy link

andrewwhitehead commented Oct 31, 2022

I was looking at implementing the hash2curve traits for bls12-381 (which has an implementation, but not using these traits currently), but ran into an issue with the CofactorGroup requirement on the GroupDigest trait:

pub trait GroupDigest: ProjectiveArithmetic
where
    ProjectivePoint<Self>: CofactorGroup,
{
    /// The field element representation for a group value with multiple elements
    type FieldElement: FromOkm + MapToCurve<Output = ProjectivePoint<Self>> + Default + Copy;
...

It would make sense for the outputs of MapToCurve to be other than a ProjectivePoint<Self> because they still needs clear_cofactor to be performed, but that's not how the requirement is used here. The output is converted into the CofactorGroup only to be converted back, and prior to that the implementation must not use arithmetic operations on the points as they may not be well defined.

It is also burdensome to implement CofactorGroup if it isn't used elsewhere, because that requires all of the related group operations to be defined: Group + GroupEncoding + GroupOps<Self::Subgroup> + GroupOpsOwned<Self::Subgroup>.

For ease of implementation and to avoid representing a non-subgroup point as a ProjectivePoint<Self> I think it might be best to extend the MapToCurve trait as follows. The add_and_clear_cofactor method can be optimized when addition is well-defined for Self::CurvePoint:

pub trait MapToCurve {
    /// The intermediate representation
    type CurvePoint;
    /// The output point
    type SubGroupPoint: group::Group;

    /// Map a field element into a point
    fn map_to_curve(&self) -> Self::CurvePoint;
    
    /// Sends the result of `map_to_curve` to the curve subgroup.
    fn clear_cofactor(point: &Self::CurvePoint) -> Self::SubGroupPoint;
    
    /// Combine two `map_to_curve` outputs into a curve subgroup point.
    fn add_and_clear_cofactor(lhs: &Self::CurvePoint, rhs: &Self::CurvePoint) -> Self::SubGroupPoint {
        Self::clear_cofactor(lhs) + Self::clear_cofactor(rhs)
    }
}
@andrewwhitehead
Copy link
Author

Additionally it seems possible that a crate might want to implement MapToCurve for multiple curves using the same FieldElement as a basis, which isn't possible at the moment. I think MapToCurve could instead be implemented for the curve itself:

pub trait MapToCurve: ProjectiveArithmetic {
    /// The intermediate representation
    type CurvePoint;
    /// The field element representation for a group value with multiple elements
    type FieldElement: FromOkm + Default + Copy;

    /// Map a field element into a point
    fn map_to_curve(element: &Self::FieldElement) -> Self::CurvePoint;

    /// Sends the result of `map_to_curve` to the curve subgroup.
    fn clear_cofactor(point: &Self::CurvePoint) -> ProjectivePoint<Self>;
    
    /// Combine two `map_to_curve` outputs into a curve subgroup point.
    fn add_and_clear_cofactor(lhs: &Self::CurvePoint, rhs: &Self::CurvePoint) -> ProjectivePoint<Self> {
        Self::clear_cofactor(lhs) + Self::clear_cofactor(rhs)
    }
}

@tarcieri
Copy link
Member

cc @daxpedda

@daxpedda
Copy link
Contributor

The proposed changes seem reasonable to me. My use-case was very limited, so I didn't have any of these problems and I also don't have any experience using hash2curve on anything else then P-256 and for OPRF and OPAQUE.

I'm happy to review any PR's, I will also contribute an OPRF crate to RustCrypto when I find time (soonish) so we can make sure compatibility remains.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants
@tarcieri @newpavlov @daxpedda @andrewwhitehead and others