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