generic_ec_curves/rust_crypto/
mod.rs1use core::fmt;
7use core::hash::{self, Hash};
8use core::marker::PhantomData;
9use core::ops::Mul;
10
11use elliptic_curve::group::cofactor::CofactorGroup;
12use elliptic_curve::hash2curve::ExpandMsgXmd;
13use elliptic_curve::ops::Reduce;
14use elliptic_curve::sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint};
15use elliptic_curve::{CurveArithmetic, FieldBytesSize, ScalarPrimitive};
16use generic_ec_core::{
17 CompressedEncoding, Curve, IntegerEncoding, NoInvalidPoints, UncompressedEncoding,
18};
19use subtle::{ConditionallySelectable, ConstantTimeEq};
20use zeroize::{DefaultIsZeroes, Zeroize};
21
22#[cfg(any(feature = "secp256k1", feature = "secp256r1", feature = "stark"))]
23use sha2::Sha256;
24
25pub use self::{curve_name::CurveName, point::RustCryptoPoint, scalar::RustCryptoScalar};
26
27mod affine_coords;
28mod curve_name;
29mod hash_to_curve;
30mod point;
31mod scalar;
32
33pub struct RustCryptoCurve<C, X> {
35 _ph: PhantomData<fn() -> (C, X)>,
36}
37
38impl<C, X> RustCryptoCurve<C, X>
39where
40 C: CurveArithmetic,
41{
42 pub fn point(point: C::ProjectivePoint) -> RustCryptoPoint<C> {
44 RustCryptoPoint(point)
45 }
46}
47
48impl<C, X> RustCryptoCurve<C, X>
49where
50 C: CurveArithmetic,
51{
52 pub fn scalar(scalar: C::Scalar) -> RustCryptoScalar<C> {
54 RustCryptoScalar(scalar)
55 }
56}
57
58#[cfg(feature = "secp256k1")]
62pub type Secp256k1 = RustCryptoCurve<k256::Secp256k1, ExpandMsgXmd<Sha256>>;
63#[cfg(feature = "secp256r1")]
67pub type Secp256r1 = RustCryptoCurve<p256::NistP256, ExpandMsgXmd<Sha256>>;
68
69#[cfg(feature = "stark")]
73pub type Stark = RustCryptoCurve<stark_curve::StarkCurve, ExpandMsgXmd<Sha256>>;
74
75impl<C, X> Curve for RustCryptoCurve<C, X>
76where
77 C: CurveName + CurveArithmetic,
78 C::ProjectivePoint: From<C::AffinePoint>
79 + CofactorGroup
80 + Copy
81 + Eq
82 + Default
83 + ConstantTimeEq
84 + ConditionallySelectable
85 + Zeroize
86 + Unpin,
87 C::AffinePoint: From<C::ProjectivePoint> + ToEncodedPoint<C> + FromEncodedPoint<C>,
88 for<'a> &'a C::ProjectivePoint: Mul<&'a C::Scalar, Output = C::ProjectivePoint>,
89 C::Scalar:
90 Reduce<C::Uint> + Eq + ConstantTimeEq + ConditionallySelectable + DefaultIsZeroes + Unpin,
91 RustCryptoScalar<C>: scalar::BytesModOrder,
92 for<'a> ScalarPrimitive<C>: From<&'a C::Scalar>,
93 FieldBytesSize<C>: ModulusSize,
94 X: 'static,
95{
96 const CURVE_NAME: &'static str = C::CURVE_NAME;
97
98 type Point = RustCryptoPoint<C>;
99 type Scalar = RustCryptoScalar<C>;
100
101 type CompressedPointArray = <Self::Point as CompressedEncoding>::Bytes;
102 type UncompressedPointArray = <Self::Point as UncompressedEncoding>::Bytes;
103
104 type ScalarArray = <Self::Scalar as IntegerEncoding>::Bytes;
105
106 type CoordinateArray = elliptic_curve::FieldBytes<C>;
107}
108
109impl<C: CurveName, X> fmt::Debug for RustCryptoCurve<C, X> {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.debug_struct("RustCryptoCurve")
112 .field("curve", &C::CURVE_NAME)
113 .finish()
114 }
115}
116
117impl<C, X> Clone for RustCryptoCurve<C, X> {
118 fn clone(&self) -> Self {
119 *self
120 }
121}
122
123impl<C, X> Copy for RustCryptoCurve<C, X> {}
124
125impl<C, X> PartialEq for RustCryptoCurve<C, X> {
126 fn eq(&self, _other: &Self) -> bool {
127 true
128 }
129}
130
131impl<C, X> Eq for RustCryptoCurve<C, X> {}
132
133impl<C, X> PartialOrd for RustCryptoCurve<C, X> {
134 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
135 Some(self.cmp(other))
136 }
137}
138
139impl<C, X> Ord for RustCryptoCurve<C, X> {
140 fn cmp(&self, _other: &Self) -> core::cmp::Ordering {
141 core::cmp::Ordering::Equal
142 }
143}
144
145impl<C, X> Hash for RustCryptoCurve<C, X>
146where
147 C: CurveName,
148{
149 fn hash<H: hash::Hasher>(&self, state: &mut H) {
150 state.write(C::CURVE_NAME.as_bytes())
151 }
152}
153
154impl<C, X> Default for RustCryptoCurve<C, X> {
155 fn default() -> Self {
156 Self { _ph: PhantomData }
157 }
158}
159
160#[cfg(feature = "secp256k1")]
166unsafe impl NoInvalidPoints for Secp256k1 {}
167#[cfg(feature = "secp256r1")]
173unsafe impl NoInvalidPoints for Secp256r1 {}
174#[cfg(feature = "stark")]
180unsafe impl NoInvalidPoints for Stark {}
181
182#[cfg(test)]
183mod tests {
184 use generic_ec_core::{
185 coords::{HasAffineX, HasAffineXAndParity, HasAffineXY},
186 Curve,
187 };
188
189 use super::{Secp256k1, Secp256r1, Stark};
190
191 fn _impls_curve<E: Curve>() {}
193 fn _exposes_affine_coords<E: HasAffineX + HasAffineXAndParity + HasAffineXY>() {}
194
195 fn _curves_impl_trait() {
196 _impls_curve::<Secp256k1>();
197 _impls_curve::<Secp256r1>();
198 _impls_curve::<Stark>();
199
200 _exposes_affine_coords::<Secp256k1>();
201 _exposes_affine_coords::<Secp256r1>();
202 _exposes_affine_coords::<Stark>();
203 }
204}