-
Notifications
You must be signed in to change notification settings - Fork 32
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
Add traits and APIs for dealing with curve coordinates #30
Comments
We have a few things we need to expose:
|
Here's the current trait heirarchy: graph RL
subgraph external
standard[Clone, Copy, Debug, Eq, Sized, Send, Sync]
additive[Add, Sub, AddAssign, SubAssign]
multiplicative[Mul, MulAssign]
Neg
Sum
end
subgraph ops
GroupOps --> additive
GroupOpsOwned -->|ref| GroupOps
ScalarMul --> multiplicative
ScalarMulOwned -->|ref| ScalarMul
end
subgraph group
Group --> standard
Group --> Sum
Group --> Neg
Group --> GroupOps
Group --> GroupOpsOwned
Group --> ScalarMul
Group --> ScalarMulOwned
GroupEncoding
WnafGroup --> Group
end
subgraph curve
Curve --> Group
Curve -->|affine| GroupOps
Curve -->|affine| GroupOpsOwned
end
subgraph prime
PrimeGroup --> Group
PrimeGroup --> GroupEncoding
PrimeCurve --> Curve
PrimeCurve --> PrimeGroup
PrimeCurveAffine --> standard
PrimeCurveAffine --> GroupEncoding
PrimeCurveAffine --> Neg
PrimeCurveAffine -->|scalar| multiplicative
PrimeCurve -.- PrimeCurveAffine
end
subgraph cofactor
CofactorGroup --> Group
CofactorGroup --> GroupEncoding
CofactorGroup -->|subgroup| GroupOps
CofactorGroup -->|subgroup| GroupOpsOwned
CofactorCurve --> Curve
CofactorCurve --> CofactorGroup
CofactorCurveAffine --> standard
CofactorCurveAffine --> GroupEncoding
CofactorCurveAffine --> Neg
CofactorCurveAffine -->|scalar| multiplicative
CofactorCurve -.- CofactorCurveAffine
end
If we add the coordinate access APIs to affine representations, then we'd need to add them to both graph RL
subgraph external
standard[Clone, Copy, Debug, Eq, Sized, Send, Sync]
additive[Add, Sub, AddAssign, SubAssign]
multiplicative[Mul, MulAssign]
Neg
Sum
end
subgraph ops
GroupOps --> additive
GroupOpsOwned -->|ref| GroupOps
ScalarMul --> multiplicative
ScalarMulOwned -->|ref| ScalarMul
end
subgraph group
Group --> standard
Group --> Sum
Group --> Neg
Group --> GroupOps
Group --> GroupOpsOwned
Group --> ScalarMul
Group --> ScalarMulOwned
GroupEncoding
WnafGroup --> Group
end
subgraph curve
Curve --> Group
Curve -->|affine| GroupOps
Curve -->|affine| GroupOpsOwned
CurveAffine --> standard
CurveAffine --> GroupEncoding
CurveAffine --> Neg
CurveAffine -->|scalar| multiplicative
Curve -.- CurveAffine
end
subgraph prime
PrimeGroup --> Group
PrimeGroup --> GroupEncoding
PrimeCurve --> Curve
PrimeCurve --> PrimeGroup
PrimeCurveAffine --> CurveAffine
PrimeCurve -.- PrimeCurveAffine
end
subgraph cofactor
CofactorGroup --> Group
CofactorGroup --> GroupEncoding
CofactorGroup -->|subgroup| GroupOps
CofactorGroup -->|subgroup| GroupOpsOwned
CofactorCurve --> Curve
CofactorCurve --> CofactorGroup
CofactorCurveAffine --> CurveAffine
CofactorCurve -.- CofactorCurveAffine
end
We might be able to avoid the extra bidirectional associated types on Alternatively, we could define a graph RL
subgraph external
standard[Clone, Copy, Debug, Eq, Sized, Send, Sync]
additive[Add, Sub, AddAssign, SubAssign]
multiplicative[Mul, MulAssign]
Neg
Sum
end
subgraph ops
GroupOps --> additive
GroupOpsOwned -->|ref| GroupOps
ScalarMul --> multiplicative
ScalarMulOwned -->|ref| ScalarMul
end
subgraph group
Group --> standard
Group --> Sum
Group --> Neg
Group --> GroupOps
Group --> GroupOpsOwned
Group --> ScalarMul
Group --> ScalarMulOwned
GroupEncoding
WnafGroup --> Group
end
subgraph curve
Curve --> Group
Curve -->|affine| GroupOps
Curve -->|affine| GroupOpsOwned
CurveCoordinates
end
subgraph prime
PrimeGroup --> Group
PrimeGroup --> GroupEncoding
PrimeCurve --> Curve
PrimeCurve --> PrimeGroup
PrimeCurveAffine --> standard
PrimeCurveAffine --> GroupEncoding
PrimeCurveAffine --> Neg
PrimeCurveAffine -->|scalar| multiplicative
PrimeCurveAffine --> CurveCoordinates
PrimeCurve -.- PrimeCurveAffine
end
subgraph cofactor
CofactorGroup --> Group
CofactorGroup --> GroupEncoding
CofactorGroup -->|subgroup| GroupOps
CofactorGroup -->|subgroup| GroupOpsOwned
CofactorCurve --> Curve
CofactorCurve --> CofactorGroup
CofactorCurveAffine --> standard
CofactorCurveAffine --> GroupEncoding
CofactorCurveAffine --> Neg
CofactorCurveAffine -->|scalar| multiplicative
CofactorCurveAffine --> CurveCoordinates
CofactorCurve -.- CofactorCurveAffine
end
|
As a general comment, supporting exotic point encodings and making the existing implementations generic and reusable have been the main reasons for having some form of coordinate access in the https://github.com/RustCrypto/elliptic-curves crates. So far our solution has been to impl these encodings in the respective crates where they can access private field members and |
See RustCrypto/elliptic-curves#50 for some historic context. After being able to get by on `AffineXCoordinate` for generic ECDH and ECDSA, #1199 added an `AffineYIsOdd` trait which was needed to enable the generic ECDSA implementation in the `ecdsa` crate to compute the "recovery ID" for signatures (which is effectively point compression for the `R` curve point). This commit consolidates `AffineXCoordinate` and `AffineYIsOdd` into an `AffineCoordinates` trait. Some observations since prior discussion in RustCrypto/elliptic-curves#50: - Access to coordinates is through bytes, namely `FieldBytes`. This is so as to avoid exposing a crate's field element type. This approach isn't type safe (base field elements and scalar field elements share the same serialization) but does make ECDSA's weird reduction of a base field element into the scalar field straightforward in generic code. - Prior to this attempts were made to extract ECDSA-specific bits into a trait to handle these conversions, but it complicates both writing generic code and optimizing performance. While this still might be worth exploring, so far those explorations have largely failed. - Generally there have been a lot of requests for coordinate access specifically for things like point serialization formats. We ended up adding "compaction" support upstream but we have had requests for several other formats (e.g. Elligator Squared) where direct coordinate access would be useful. This trait can hopefully be replaced by a coordinate access API provided by the `group` crate in the future. See zkcrypto/group#30
See RustCrypto/elliptic-curves#50 for some historic context. After being able to get by on `AffineXCoordinate` for generic ECDH and ECDSA, #1199 added an `AffineYIsOdd` trait which was needed to enable the generic ECDSA implementation in the `ecdsa` crate to compute the "recovery ID" for signatures (which is effectively point compression for the `R` curve point). This commit consolidates `AffineXCoordinate` and `AffineYIsOdd` into an `AffineCoordinates` trait. Some observations since prior discussion in RustCrypto/elliptic-curves#50: - Access to coordinates is through bytes, namely `FieldBytes`. This is so as to avoid exposing a crate's field element type. This approach isn't type safe (base field elements and scalar field elements share the same serialization) but does make ECDSA's weird reduction of a base field element into the scalar field straightforward in generic code. - Prior to this attempts were made to extract ECDSA-specific bits into a trait to handle these conversions, but it complicates both writing generic code and optimizing performance. While this still might be worth exploring, so far those explorations have largely failed. - Generally there have been a lot of requests for coordinate access specifically for things like point serialization formats. We ended up adding "compaction" support upstream but we have had requests for several other formats (e.g. Elligator Squared) where direct coordinate access would be useful. This trait can hopefully be replaced by a coordinate access API provided by the `group` crate in the future. See zkcrypto/group#30
I was able to implement a We definitely want to introduce some concept of a curve model into whatever types or traits we build (#29 (comment)). Doing so would help with zcash/pasta_curves#41 as it would be a place we could easily expose the curve constants. |
In the case of dalek-cryptography/curve25519-dalek#553 we have a request for obtaining extended twisted Edwards coordinates (i.e. X/Y/Z/T). That may be esoteric enough a trait-based abstraction won't help there. The main other use cases for this we have for @RustCrypto are all accessing affine coordinates, almost all of which are implementations of various wire formats for encoding those coordinates e.g. compact encoding, Elligator (Squared) |
I'm not particularly interested in generically exposing the projective coordinates. We do have a use case for it in |
We use extension traits to limit how generic the generic code can be, forcing it to be aware of the specific curve model that the coordinates are associated with. Closes #30.
I've been asked by @tarcieri to move the discussion from elliptic-curves/#937 to here. I am writing a Schnorr protocol and need access to the projective coordinates. Well, actually, I don't care about the coordinates per-se but some encoding of the projective point that I can use for commitment/decommitment, and to use on transcript. Now, my only option is to switch to the affine coordinates. However, this is extremely costly in computation (e.g., in So, I need a way to uniquely encode projective points directly; and be able to transition in and out from those values and into a Tony also asked me whether I care about other affine points mapping to the same projective point. I don't. Malicious provers won't be able to use that to their advantage, as they would be committing to the same value that the verifier would be using. Thoughts on this? Thanks. |
The original motivation for removing the
Base
associated type from the oldCurveProjective
andCurveAffine
traits in 15bc628 was that dealing in coordinates directly is almost always incorrect for cryptographic protocols, so we didn't expose them (instead leaving it to the concrete curve impls to handle such needs themselves). And if we don't expose the coordinates anywhere, then there is no reason to expose the base field (the associated type was completely unused at the time).However, in proving system contexts it is necessary to have access to the coordinates in order to re-implement EC arithmetic inside a circuit. My original plan at the time of the above refactor was to move such curve implementations concretely into the curve crates themselves, but that leads to some awkward dependency tree management (we'd need to split crates like
bellman
andhalo2_proofs
up in a way that enabled this). This is why thepasta_curves
crate currently exposes the base field and coordinates APIs via aCurveExt
trait, but we explicitly want to make that trait obsolete by upstreaming its functionality here (zcash/pasta_curves#41), so we need to develop a solution for it.The text was updated successfully, but these errors were encountered: