elliptic-curve: Use a single `Point` type instead of `AffinePoint` and `ProjectivePoint`
As discussed in https://github.com/dalek-cryptography/curve25519-dalek/pull/746#issuecomment-2909894366. AffinePoint and ProjectivePoint weakly map to some elliptic curve implementations. Some implementations don't use the projective variant of their points (thinking of montgomery curves) and some only use the projective or another variant of point. For example, ed25519 uses points in $\mathbb{P}^1 \times \mathbb{P}^1$ space.
We might be able to construct a better abstraction for elliptic-curves by only using a single Point associated type. I am writing this here to stir up thoughts & opinions around this idea.
I think it would be interesting to experiment with an enum Point over AffinePoint and ProjectivePoint which can select the appropriate formulas to use in the https://github.com/RustCrypto/elliptic-curves crates. If this could be made to work, then we could attempt to change the traits to work that way. Note that we would still probably retain the types and all of the associated trait impls (the enum would likewise have public variant types).
I think it would definitely make for a simpler user-facing interface to have a single Point type to deal with, which is likely why curve25519-dalek never exposed AffinePoint, and it benefits less from things like formulas explicitly for operating on affine points. Point could be used by anyone who doesn't understand or care about the difference between AffinePoint and ProjectivePoint.
All that said, as you noted we are trying to wrap up the most recent release series and this would be a pretty big change, and one I would prefer not to hold up the release.
Maybe one thing we could experiment with prior to the next release is at least partially undoing #1196. I unified the traits for the sake of simplicity, but unfortunately that resulted in an abstraction which isn't one-size-fits-all.
I'm not really a big fan of replacing AffinePoint and ProjectivePoint with an enum, but I think adding the enum would be great.
Just wanted to leave a note here that this would be very useful for hash2curve because not all mappings output the same form. E.g. Edwards and Montgomery curve mapping return projective points, Weierstrass curve mapping return affine points. Depending on what users do with that afterwards, encode or arithmetic operations, this can introduce an unnecessarily expensive inversion operation.
So it would be quite useful if hash2curve operations just return that enum and let users decide how to proceed.
@daxpedda yes, that would be the idea, an enum like:
pub enum Point<C: Curve> {
Affine(AffinePoint<C>),
Projective(ProjectivePoint<C>),
}
Everything else would remain the same
It's possible a trait would usually makes more sense here:
pub trait Point<C> : Into<AffinePoint<C>> + Into<ProjectivePoint<C>> {
fn into_affine(self) -> AffinePoint<C> { self.into() }
fn into_projective(self) -> ProjectivePoint<C> { self.into() }
}
@burdges if you hide the concrete type, you can't know when to select the mixed addition formulas because you've received a mixture of projective and affine inputs
I also propose adding the same for NonIdentityPoint. We would have to figure out what to do with the naming conflict, unless we split the current NonIdentityPoint into two types as suggested in #2022.