generic_ec_curves/rust_crypto/
point.rs1use core::cmp;
2use core::hash::{self, Hash};
3
4use elliptic_curve::group::cofactor::CofactorGroup;
5use elliptic_curve::{
6 sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
7 CurveArithmetic, FieldBytesSize, Group,
8};
9use generic_ec_core::*;
10use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
11use zeroize::Zeroize;
12
13pub struct RustCryptoPoint<E: CurveArithmetic>(pub E::ProjectivePoint);
15
16impl<E: CurveArithmetic> Additive for RustCryptoPoint<E> {
17 #[inline]
18 fn add(a: &Self, b: &Self) -> Self {
19 RustCryptoPoint(a.0 + b.0)
20 }
21
22 #[inline]
23 fn sub(a: &Self, b: &Self) -> Self {
24 RustCryptoPoint(a.0 - b.0)
25 }
26
27 #[inline]
28 fn negate(x: &Self) -> Self {
29 RustCryptoPoint(-x.0)
30 }
31
32 #[inline]
33 fn double(x: &Self) -> Self {
34 RustCryptoPoint(x.0.double())
35 }
36}
37
38impl<E: CurveArithmetic> From<CurveGenerator> for RustCryptoPoint<E> {
39 #[inline]
40 fn from(_: CurveGenerator) -> Self {
41 RustCryptoPoint(E::ProjectivePoint::generator())
42 }
43}
44
45impl<E: CurveArithmetic> Zero for RustCryptoPoint<E> {
46 #[inline]
47 fn zero() -> Self {
48 RustCryptoPoint(E::ProjectivePoint::identity())
49 }
50
51 #[inline]
52 fn is_zero(x: &Self) -> Choice {
53 x.0.is_identity()
54 }
55}
56
57impl<E: CurveArithmetic> OnCurve for RustCryptoPoint<E> {
58 #[inline]
59 fn is_on_curve(&self) -> Choice {
60 Choice::from(1)
61 }
62}
63
64impl<E> SmallFactor for RustCryptoPoint<E>
65where
66 E: CurveArithmetic,
67 E::ProjectivePoint: CofactorGroup,
68{
69 #[inline]
70 fn is_torsion_free(&self) -> Choice {
71 self.0.is_torsion_free()
72 }
73}
74
75impl<E> ConstantTimeEq for RustCryptoPoint<E>
76where
77 E: CurveArithmetic,
78 E::ProjectivePoint: ConstantTimeEq,
79{
80 #[inline]
81 fn ct_eq(&self, other: &Self) -> Choice {
82 self.0.ct_eq(&other.0)
83 }
84}
85
86impl<E> ConditionallySelectable for RustCryptoPoint<E>
87where
88 E: CurveArithmetic,
89 E::ProjectivePoint: ConditionallySelectable,
90{
91 #[inline]
92 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
93 Self(E::ProjectivePoint::conditional_select(&a.0, &b.0, choice))
94 }
95
96 #[inline]
97 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
98 self.0.conditional_assign(&other.0, choice)
99 }
100
101 #[inline]
102 fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
103 E::ProjectivePoint::conditional_swap(&mut a.0, &mut b.0, choice)
104 }
105}
106
107impl<E> CompressedEncoding for RustCryptoPoint<E>
108where
109 E: CurveArithmetic,
110 E::AffinePoint: ToEncodedPoint<E> + From<E::ProjectivePoint>,
111 FieldBytesSize<E>: ModulusSize,
112{
113 type Bytes = elliptic_curve::sec1::CompressedPoint<E>;
114 fn to_bytes_compressed(&self) -> Self::Bytes {
115 let point_encoded = E::AffinePoint::from(self.0).to_encoded_point(true);
116
117 let mut bytes = Self::Bytes::default();
118 if !bool::from(Self::is_zero(self)) {
119 bytes.copy_from_slice(point_encoded.as_bytes());
120 }
121
122 bytes
123 }
124}
125
126impl<E> UncompressedEncoding for RustCryptoPoint<E>
127where
128 E: CurveArithmetic,
129 E::AffinePoint: ToEncodedPoint<E> + From<E::ProjectivePoint>,
130 FieldBytesSize<E>: ModulusSize,
131{
132 type Bytes = elliptic_curve::sec1::UncompressedPoint<E>;
133 fn to_bytes_uncompressed(&self) -> Self::Bytes {
134 let point_encoded = E::AffinePoint::from(self.0).to_encoded_point(false);
135
136 let mut bytes = Self::Bytes::default();
137 if !bool::from(Self::is_zero(self)) {
138 bytes.copy_from_slice(point_encoded.as_bytes());
139 }
140
141 bytes
142 }
143}
144
145impl<E> Decode for RustCryptoPoint<E>
146where
147 E: CurveArithmetic,
148 E::AffinePoint: FromEncodedPoint<E> + Into<E::ProjectivePoint>,
149 FieldBytesSize<E>: ModulusSize,
150{
151 fn decode(mut bytes: &[u8]) -> Option<Self> {
152 let all_zero = bytes.iter().all(|b| *b == 0);
153 if all_zero {
154 bytes = &[0]
157 }
158 let encoded_point = EncodedPoint::<E>::from_bytes(bytes).ok()?;
159 Option::from(E::AffinePoint::from_encoded_point(&encoded_point))
160 .map(|point: E::AffinePoint| Self(point.into()))
161 }
162}
163
164impl<E> Clone for RustCryptoPoint<E>
165where
166 E: CurveArithmetic,
167{
168 fn clone(&self) -> Self {
169 *self
170 }
171}
172
173impl<E> Copy for RustCryptoPoint<E>
174where
175 E: CurveArithmetic,
176 E::ProjectivePoint: Copy,
177{
178}
179
180impl<E> Zeroize for RustCryptoPoint<E>
181where
182 E: CurveArithmetic,
183 E::ProjectivePoint: Zeroize,
184{
185 fn zeroize(&mut self) {
186 self.0.zeroize()
187 }
188}
189
190impl<E> PartialEq for RustCryptoPoint<E>
191where
192 E: CurveArithmetic,
193 E::ProjectivePoint: PartialEq,
194{
195 fn eq(&self, other: &Self) -> bool {
196 self.0 == other.0
197 }
198}
199
200impl<E> Eq for RustCryptoPoint<E>
201where
202 E: CurveArithmetic,
203 E::ProjectivePoint: Eq,
204{
205}
206
207impl<E> Hash for RustCryptoPoint<E>
208where
209 E: CurveArithmetic,
210 E::ProjectivePoint: Hash,
211{
212 fn hash<H: hash::Hasher>(&self, state: &mut H) {
213 self.0.hash(state)
214 }
215}
216
217impl<E> PartialOrd for RustCryptoPoint<E>
218where
219 E: CurveArithmetic,
220 E::ProjectivePoint: PartialOrd,
221{
222 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
223 self.0.partial_cmp(&other.0)
224 }
225}
226
227impl<E> Ord for RustCryptoPoint<E>
228where
229 E: CurveArithmetic,
230 E::ProjectivePoint: Ord,
231{
232 fn cmp(&self, other: &Self) -> cmp::Ordering {
233 self.0.cmp(&other.0)
234 }
235}
236
237impl<E> Default for RustCryptoPoint<E>
238where
239 E: CurveArithmetic,
240 E::ProjectivePoint: Default,
241{
242 fn default() -> Self {
243 Self(Default::default())
244 }
245}