generic_ec_curves/rust_crypto/
affine_coords.rs1use 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}