generic_ec_curves/rust_crypto/
affine_coords.rs

1use elliptic_curve::generic_array::GenericArray;
2use elliptic_curve::sec1::{
3    CompressedPointSize, Coordinates, EncodedPoint, FromEncodedPoint, Tag, ToEncodedPoint,
4};
5use elliptic_curve::{CurveArithmetic, FieldBytesSize};
6use generic_ec_core::coords::{HasAffineX, HasAffineXAndParity, HasAffineXY, HasAffineY, Parity};
7
8use super::{RustCryptoCurve, RustCryptoPoint};
9
10impl<C, X> HasAffineX for RustCryptoCurve<C, X>
11where
12    C: CurveArithmetic,
13    FieldBytesSize<C>: elliptic_curve::sec1::ModulusSize,
14    C::AffinePoint: ToEncodedPoint<C> + From<C::ProjectivePoint>,
15    RustCryptoCurve<C, X>: generic_ec_core::Curve<
16        Point = RustCryptoPoint<C>,
17        CoordinateArray = elliptic_curve::FieldBytes<C>,
18    >,
19{
20    fn x(point: &Self::Point) -> Option<Self::CoordinateArray> {
21        match C::AffinePoint::from(point.0)
22            .to_encoded_point(false)
23            .coordinates()
24        {
25            Coordinates::Identity => None,
26            Coordinates::Uncompressed { x, .. } => Some(x.clone()),
27            Coordinates::Compact { .. } | Coordinates::Compressed { .. } => {
28                unreachable!("point was encoded in uncompressed form")
29            }
30        }
31    }
32}
33
34impl<C, X> HasAffineXAndParity for RustCryptoCurve<C, X>
35where
36    C: CurveArithmetic,
37    FieldBytesSize<C>: elliptic_curve::sec1::ModulusSize,
38    C::AffinePoint: ToEncodedPoint<C>
39        + FromEncodedPoint<C>
40        + From<C::ProjectivePoint>
41        + Into<C::ProjectivePoint>,
42    RustCryptoCurve<C, X>: generic_ec_core::Curve<
43        Point = RustCryptoPoint<C>,
44        CoordinateArray = elliptic_curve::FieldBytes<C>,
45    >,
46{
47    fn x_and_parity(point: &Self::Point) -> Option<(Self::CoordinateArray, Parity)> {
48        match C::AffinePoint::from(point.0)
49            .to_encoded_point(true)
50            .coordinates()
51        {
52            Coordinates::Identity => None,
53            Coordinates::Compressed { x, y_is_odd } => {
54                Some((x.clone(), if y_is_odd { Parity::Odd } else { Parity::Even }))
55            }
56            Coordinates::Compact { .. } | Coordinates::Uncompressed { .. } => {
57                unreachable!("point was encoded in uncompressed form")
58            }
59        }
60    }
61
62    fn from_x_and_parity(x: &Self::CoordinateArray, y_parity: Parity) -> Option<Self::Point> {
63        let mut encoding = GenericArray::<u8, CompressedPointSize<C>>::default();
64        let tag = match y_parity {
65            Parity::Even => Tag::CompressedEvenY,
66            Parity::Odd => Tag::CompressedOddY,
67        };
68        encoding[0] = tag as u8;
69        encoding[1..].copy_from_slice(x);
70
71        let encoded_point = EncodedPoint::<C>::from_bytes(&encoding).ok()?;
72        Option::from(C::AffinePoint::from_encoded_point(&encoded_point))
73            .map(|point: C::AffinePoint| RustCryptoPoint(point.into()))
74    }
75}
76
77impl<C, X> HasAffineY for RustCryptoCurve<C, X>
78where
79    C: CurveArithmetic,
80    FieldBytesSize<C>: elliptic_curve::sec1::ModulusSize,
81    C::AffinePoint: ToEncodedPoint<C> + From<C::ProjectivePoint>,
82    RustCryptoCurve<C, X>: generic_ec_core::Curve<
83        Point = RustCryptoPoint<C>,
84        CoordinateArray = elliptic_curve::FieldBytes<C>,
85    >,
86{
87    fn y(point: &Self::Point) -> Option<Self::CoordinateArray> {
88        match C::AffinePoint::from(point.0)
89            .to_encoded_point(false)
90            .coordinates()
91        {
92            Coordinates::Identity => None,
93            Coordinates::Uncompressed { y, .. } => Some(y.clone()),
94            Coordinates::Compact { .. } | Coordinates::Compressed { .. } => {
95                unreachable!("point was encoded in uncompressed form")
96            }
97        }
98    }
99}
100
101impl<C, X> HasAffineXY for RustCryptoCurve<C, X>
102where
103    C: CurveArithmetic,
104    FieldBytesSize<C>: elliptic_curve::sec1::ModulusSize,
105    C::AffinePoint: ToEncodedPoint<C>
106        + FromEncodedPoint<C>
107        + From<C::ProjectivePoint>
108        + Into<C::ProjectivePoint>,
109    RustCryptoCurve<C, X>: generic_ec_core::Curve<
110        Point = RustCryptoPoint<C>,
111        CoordinateArray = elliptic_curve::FieldBytes<C>,
112    >,
113{
114    fn x_and_y(point: &Self::Point) -> Option<(Self::CoordinateArray, Self::CoordinateArray)> {
115        match C::AffinePoint::from(point.0)
116            .to_encoded_point(false)
117            .coordinates()
118        {
119            Coordinates::Identity => None,
120            Coordinates::Uncompressed { x, y } => Some((x.clone(), y.clone())),
121            Coordinates::Compact { .. } | Coordinates::Compressed { .. } => {
122                unreachable!("point was encoded in uncompressed form")
123            }
124        }
125    }
126
127    fn from_x_and_y(x: &Self::CoordinateArray, y: &Self::CoordinateArray) -> Option<Self::Point> {
128        let encoded_point = EncodedPoint::<C>::from_affine_coordinates(x, y, false);
129        Option::from(C::AffinePoint::from_encoded_point(&encoded_point))
130            .map(|point: C::AffinePoint| RustCryptoPoint(point.into()))
131    }
132}