primitives/algebra/elliptic_curve/
point.rs

1use std::{
2    hash::Hash,
3    iter::Sum,
4    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5    sync::Arc,
6};
7
8use elliptic_curve::group::{Group, GroupEncoding};
9use rand::{distributions::Standard, prelude::Distribution, RngCore};
10use serde::{Deserialize, Serialize};
11use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
12
13use crate::{
14    algebra::elliptic_curve::{
15        curve::{FromExtendedEdwards, PointAtInfinityError, ToExtendedEdwards},
16        BaseFieldElement,
17        Curve,
18        Scalar,
19        ScalarAsExtension,
20    },
21    errors::SerializationError,
22    impl_borrow_variants,
23    impl_commutative,
24    sharing::unauthenticated::AdditiveShares,
25};
26
27/// A point on a given curve.
28#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash)]
29pub struct Point<C: Curve>(pub(crate) C::Point);
30impl<C: Curve> Unpin for Point<C> {}
31
32impl<C: Curve> Serialize for Point<C> {
33    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
34        let bytes = self.0.to_bytes();
35        serde_bytes::serialize(bytes.as_ref(), serializer)
36    }
37}
38
39impl<'de, C: Curve> Deserialize<'de> for Point<C> {
40    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
41        let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
42        let endian_bytes = if C::POINT_BIG_ENDIAN {
43            Point::from_be_bytes(bytes)
44        } else {
45            Point::from_le_bytes(bytes)
46        };
47        let point = endian_bytes.map_err(|err| {
48            serde::de::Error::custom(format!("Failed to deserialize curve point: {err:?}"))
49        })?;
50        Ok(point)
51    }
52}
53
54// ------------------------
55// | Misc Implementations |
56// ------------------------
57
58impl<C: Curve> Point<C> {
59    /// The additive identity in the curve group
60    pub fn identity() -> Point<C> {
61        Point(C::Point::identity())
62    }
63
64    pub fn new(point: C::Point) -> Point<C> {
65        Point(point)
66    }
67
68    /// Check whether the given point is the identity point in the group
69    pub fn is_identity(&self) -> Choice {
70        self.ct_eq(&Point::identity())
71    }
72
73    /// Return the wrapped type
74    pub fn inner(&self) -> C::Point {
75        self.0
76    }
77
78    /// The group generator
79    pub fn generator() -> Point<C> {
80        Point(<C::Point as Group>::generator())
81    }
82
83    /// Deserialize a point from a byte buffer
84    /// TODO: Check this is constant-time
85    pub fn from_be_bytes(bytes: &[u8]) -> Result<Point<C>, SerializationError> {
86        let mut encoding = <C::Point as GroupEncoding>::Repr::default();
87
88        if C::POINT_BIG_ENDIAN {
89            encoding.as_mut().copy_from_slice(bytes);
90        } else {
91            encoding.as_mut().copy_from_slice(bytes);
92            encoding.as_mut().reverse();
93        }
94
95        let point = Option::from(C::Point::from_bytes(&encoding))
96            .ok_or(SerializationError::DeserializationFailed)?;
97        Ok(Point(point))
98    }
99
100    /// Deserialize a point from a byte buffer
101    /// TODO: Check this is constant-time
102    pub fn from_le_bytes(bytes: &[u8]) -> Result<Point<C>, SerializationError> {
103        let mut encoding = <C::Point as GroupEncoding>::Repr::default();
104
105        if C::POINT_BIG_ENDIAN {
106            encoding.as_mut().copy_from_slice(bytes);
107            encoding.as_mut().reverse();
108        } else {
109            encoding.as_mut().copy_from_slice(bytes);
110        }
111
112        let point = Option::from(C::Point::from_bytes(&encoding))
113            .ok_or(SerializationError::DeserializationFailed)?;
114        Ok(Point(point))
115    }
116
117    /// Serialize the point to a byte buffer
118    pub fn to_bytes(&self) -> Arc<[u8]> {
119        self.0.to_bytes().as_ref().into()
120    }
121
122    pub fn from_extended_edwards(coordinates: [BaseFieldElement<C>; 4]) -> Option<Point<C>> {
123        C::Point::from_extended_edwards(coordinates).map(Point)
124    }
125
126    pub fn to_extended_edwards(self) -> Result<[BaseFieldElement<C>; 4], PointAtInfinityError> {
127        self.0.to_extended_edwards()
128    }
129}
130
131impl<C: Curve> Distribution<Point<C>> for Standard {
132    #[inline]
133    fn sample<R: RngCore + ?Sized>(&self, rng: &mut R) -> Point<C> {
134        Point(C::Point::random(rng))
135    }
136}
137
138// ------------------------------------
139// | Curve Arithmetic Implementations |
140// ------------------------------------
141
142// === Addition === //
143
144impl<C: Curve> Add<&Point<C>> for &Point<C> {
145    type Output = Point<C>;
146
147    #[inline]
148    fn add(self, rhs: &Point<C>) -> Self::Output {
149        Point(self.0 + rhs.0)
150    }
151}
152impl_borrow_variants!(Point<C>, Add, add, +, Point<C>, C: Curve);
153
154// === AddAssign === //
155
156impl<C: Curve> AddAssign for Point<C> {
157    #[inline]
158    fn add_assign(&mut self, rhs: Self) {
159        self.0 += rhs.0;
160    }
161}
162
163impl<'a, C: Curve> AddAssign<&'a Point<C>> for Point<C> {
164    #[inline]
165    fn add_assign(&mut self, rhs: &'a Point<C>) {
166        self.0 += rhs.0;
167    }
168}
169
170// === Subtraction === //
171
172impl<C: Curve> Sub<&Point<C>> for &Point<C> {
173    type Output = Point<C>;
174
175    #[inline]
176    fn sub(self, rhs: &Point<C>) -> Self::Output {
177        Point(self.0 - rhs.0)
178    }
179}
180impl_borrow_variants!(Point<C>, Sub, sub, -, Point<C>, C: Curve);
181
182// === SubAssign === //
183
184impl<C: Curve> SubAssign for Point<C> {
185    #[inline]
186    fn sub_assign(&mut self, rhs: Self) {
187        self.0 -= rhs.0;
188    }
189}
190
191impl<'a, C: Curve> SubAssign<&'a Point<C>> for Point<C> {
192    #[inline]
193    fn sub_assign(&mut self, rhs: &'a Point<C>) {
194        self.0 -= rhs.0;
195    }
196}
197
198// === Negation === //
199
200impl<C: Curve> Neg for &Point<C> {
201    type Output = Point<C>;
202
203    #[inline]
204    fn neg(self) -> Self::Output {
205        Point(-self.0)
206    }
207}
208impl_borrow_variants!(Point<C>, Neg, neg, -, C: Curve);
209
210// === Scalar Multiplication === //
211
212impl<C: Curve> Mul<&ScalarAsExtension<C>> for &Point<C> {
213    type Output = Point<C>;
214
215    #[inline]
216    fn mul(self, rhs: &ScalarAsExtension<C>) -> Self::Output {
217        Point(self.0 * rhs.0)
218    }
219}
220impl_borrow_variants!(Point<C>, Mul, mul, *, ScalarAsExtension<C>, C: Curve);
221impl_commutative!(Point<C>, Mul, mul, *, ScalarAsExtension<C>, C: Curve);
222
223impl<C: Curve> Mul<&Scalar<C>> for &Point<C> {
224    type Output = Point<C>;
225
226    #[inline]
227    fn mul(self, rhs: &Scalar<C>) -> Self::Output {
228        Point(self.0 * rhs.0)
229    }
230}
231impl_borrow_variants!(Point<C>, Mul, mul, *, Scalar<C>, C: Curve);
232impl_commutative!(Point<C>, Mul, mul, *, Scalar<C>, C: Curve);
233
234// === MulAssign === //
235
236impl<C: Curve> MulAssign<ScalarAsExtension<C>> for Point<C> {
237    #[inline]
238    fn mul_assign(&mut self, rhs: ScalarAsExtension<C>) {
239        self.0 *= rhs.0;
240    }
241}
242
243impl<C: Curve> MulAssign<&ScalarAsExtension<C>> for Point<C> {
244    #[inline]
245    fn mul_assign(&mut self, rhs: &ScalarAsExtension<C>) {
246        self.0 *= rhs.0;
247    }
248}
249
250impl<C: Curve> MulAssign<Scalar<C>> for Point<C> {
251    #[inline]
252    fn mul_assign(&mut self, rhs: Scalar<C>) {
253        self.0 *= rhs.0;
254    }
255}
256
257impl<C: Curve> MulAssign<&Scalar<C>> for Point<C> {
258    #[inline]
259    fn mul_assign(&mut self, rhs: &Scalar<C>) {
260        self.0 *= rhs.0;
261    }
262}
263
264// === Equality === //
265
266impl<C: Curve> ConstantTimeEq for Point<C> {
267    #[inline]
268    fn ct_eq(&self, other: &Self) -> Choice {
269        self.0.ct_eq(&other.0)
270    }
271}
272
273impl<C: Curve> ConditionallySelectable for Point<C> {
274    #[inline]
275    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
276        let selected = C::Point::conditional_select(&a.0, &b.0, choice);
277        Point(selected)
278    }
279}
280
281// === Other === //
282
283impl<C: Curve> AdditiveShares for Point<C> {}
284
285// === Iterator traits === //
286
287impl<C: Curve> Sum for Point<C> {
288    #[inline]
289    fn sum<I: Iterator<Item = Point<C>>>(iter: I) -> Self {
290        iter.fold(Point::identity(), |acc, x| acc + x)
291    }
292}
293
294impl<'a, C: Curve> Sum<&'a Point<C>> for Point<C> {
295    #[inline]
296    fn sum<I: Iterator<Item = &'a Point<C>>>(iter: I) -> Self {
297        iter.fold(Point::identity(), |acc, x| acc + x)
298    }
299}