generic_ec_curves/rust_crypto/
point.rs

1use 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
13/// Point wrapper
14pub 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            // This is the only representation of identity point recognized
155            // by `elliptic-curve` library
156            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}