generic_ec_curves/rust_crypto/
scalar.rs1use core::ops::Mul;
2
3use elliptic_curve::bigint::{ArrayEncoding, ByteArray, U256, U512};
4use elliptic_curve::{Curve, CurveArithmetic, Field, Group, PrimeField, ScalarPrimitive};
5use generic_ec_core::{
6 Additive, CurveGenerator, IntegerEncoding, Invertible, Multiplicative, One, Reduce, Samplable,
7 Zero,
8};
9use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
10use zeroize::DefaultIsZeroes;
11
12pub struct RustCryptoScalar<E: CurveArithmetic>(pub E::Scalar);
14
15impl<E: CurveArithmetic> Additive for RustCryptoScalar<E> {
16 fn add(a: &Self, b: &Self) -> Self {
17 Self(a.0 + b.0)
18 }
19
20 fn sub(a: &Self, b: &Self) -> Self {
21 Self(a.0 - b.0)
22 }
23
24 fn negate(x: &Self) -> Self {
25 Self(-x.0)
26 }
27}
28
29impl<E: CurveArithmetic> Multiplicative<RustCryptoScalar<E>> for RustCryptoScalar<E> {
30 type Output = RustCryptoScalar<E>;
31
32 fn mul(a: &Self, b: &RustCryptoScalar<E>) -> Self::Output {
33 Self(a.0 * b.0)
34 }
35}
36
37impl<E> Multiplicative<super::RustCryptoPoint<E>> for RustCryptoScalar<E>
38where
39 E: CurveArithmetic,
40 for<'a> &'a E::ProjectivePoint: Mul<&'a E::Scalar, Output = E::ProjectivePoint>,
41{
42 type Output = super::RustCryptoPoint<E>;
43
44 fn mul(a: &Self, b: &super::RustCryptoPoint<E>) -> Self::Output {
45 super::RustCryptoPoint(b.0 * a.0)
46 }
47}
48
49impl<E> Multiplicative<CurveGenerator> for RustCryptoScalar<E>
50where
51 E: CurveArithmetic,
52 for<'a> &'a E::ProjectivePoint: Mul<&'a E::Scalar, Output = E::ProjectivePoint>,
53{
54 type Output = super::RustCryptoPoint<E>;
55
56 fn mul(a: &Self, _b: &CurveGenerator) -> Self::Output {
57 super::RustCryptoPoint(E::ProjectivePoint::generator() * a.0)
58 }
59}
60
61impl<E: CurveArithmetic> Invertible for RustCryptoScalar<E> {
62 fn invert(x: &Self) -> CtOption<Self> {
63 x.0.invert().map(Self)
64 }
65}
66
67impl<E: CurveArithmetic> Zero for RustCryptoScalar<E> {
68 fn zero() -> Self {
69 Self(E::Scalar::ZERO)
70 }
71
72 fn is_zero(x: &Self) -> subtle::Choice {
73 x.0.is_zero()
74 }
75}
76
77impl<E: CurveArithmetic> One for RustCryptoScalar<E> {
78 fn one() -> Self {
79 Self(E::Scalar::ONE)
80 }
81
82 fn is_one(x: &Self) -> Choice {
83 x.0.ct_eq(&E::Scalar::ONE)
84 }
85}
86
87impl<E: CurveArithmetic> Samplable for RustCryptoScalar<E> {
88 fn random<R: rand_core::RngCore>(rng: &mut R) -> Self {
89 let mut bytes: <E::Scalar as PrimeField>::Repr = Default::default();
90
91 loop {
92 rng.fill_bytes(bytes.as_mut());
93
94 if let Some(scalar) = <E::Scalar as PrimeField>::from_repr_vartime(bytes.clone()) {
95 break Self(scalar);
96 }
97 }
98 }
99}
100
101impl<E: CurveArithmetic> Default for RustCryptoScalar<E> {
102 fn default() -> Self {
103 Self(Default::default())
104 }
105}
106
107impl<E: CurveArithmetic> Clone for RustCryptoScalar<E> {
108 fn clone(&self) -> Self {
109 *self
110 }
111}
112
113impl<E: CurveArithmetic> Copy for RustCryptoScalar<E> {}
114
115impl<E> DefaultIsZeroes for RustCryptoScalar<E>
116where
117 E: CurveArithmetic,
118 E::Scalar: DefaultIsZeroes,
119{
120}
121
122impl<E> PartialEq for RustCryptoScalar<E>
123where
124 E: CurveArithmetic,
125 E::Scalar: PartialEq,
126{
127 fn eq(&self, other: &Self) -> bool {
128 self.0 == other.0
129 }
130}
131
132impl<E> Eq for RustCryptoScalar<E>
133where
134 E: CurveArithmetic,
135 E::Scalar: Eq,
136{
137}
138
139impl<E> ConstantTimeEq for RustCryptoScalar<E>
140where
141 E: CurveArithmetic,
142 E::Scalar: ConstantTimeEq,
143{
144 fn ct_eq(&self, other: &Self) -> Choice {
145 self.0.ct_eq(&other.0)
146 }
147}
148
149impl<E> ConditionallySelectable for RustCryptoScalar<E>
150where
151 E: CurveArithmetic,
152 E::Scalar: ConditionallySelectable,
153{
154 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
155 Self(E::Scalar::conditional_select(&a.0, &b.0, choice))
156 }
157}
158
159impl<E: CurveArithmetic + Curve> IntegerEncoding for RustCryptoScalar<E>
160where
161 for<'s> ScalarPrimitive<E>: From<&'s E::Scalar>,
162 E::Scalar: elliptic_curve::ops::Reduce<E::Uint>,
163 Self: BytesModOrder,
164{
165 type Bytes = ByteArray<E::Uint>;
166
167 fn to_be_bytes(&self) -> Self::Bytes {
168 let scalar_core = ScalarPrimitive::<E>::from(&self.0);
169 let uint = scalar_core.as_uint();
170 uint.to_be_byte_array()
171 }
172
173 fn to_le_bytes(&self) -> Self::Bytes {
174 let scalar_core = ScalarPrimitive::<E>::from(&self.0);
175 let uint = scalar_core.as_uint();
176 uint.to_le_byte_array()
177 }
178
179 fn from_be_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
180 let uint = E::Uint::from_be_byte_array(bytes.clone());
181 let scalar_core: Option<ScalarPrimitive<E>> = ScalarPrimitive::<E>::new(uint).into();
182 Some(Self(E::Scalar::from(scalar_core?)))
183 }
184
185 fn from_le_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
186 let uint = E::Uint::from_le_byte_array(bytes.clone());
187 let scalar_core: Option<ScalarPrimitive<E>> = ScalarPrimitive::<E>::new(uint).into();
188 Some(Self(E::Scalar::from(scalar_core?)))
189 }
190
191 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
192 <Self as BytesModOrder>::from_be_bytes_mod_order(bytes)
193 }
194 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
195 <Self as BytesModOrder>::from_le_bytes_mod_order(bytes)
196 }
197}
198
199impl<E: CurveArithmetic + Curve> Reduce<32> for RustCryptoScalar<E>
200where
201 E::Scalar: elliptic_curve::ops::Reduce<U256>,
202{
203 fn from_be_array_mod_order(bytes: &[u8; 32]) -> Self {
204 Self(elliptic_curve::ops::Reduce::<U256>::reduce(
205 U256::from_be_byte_array((*bytes).into()),
206 ))
207 }
208 fn from_le_array_mod_order(bytes: &[u8; 32]) -> Self {
209 Self(elliptic_curve::ops::Reduce::<U256>::reduce(
210 U256::from_le_byte_array((*bytes).into()),
211 ))
212 }
213}
214
215impl<E: CurveArithmetic + Curve> Reduce<64> for RustCryptoScalar<E>
216where
217 E::Scalar: elliptic_curve::ops::Reduce<U512>,
218{
219 fn from_be_array_mod_order(bytes: &[u8; 64]) -> Self {
220 Self(elliptic_curve::ops::Reduce::<U512>::reduce(
221 U512::from_be_byte_array((*bytes).into()),
222 ))
223 }
224 fn from_le_array_mod_order(bytes: &[u8; 64]) -> Self {
225 Self(elliptic_curve::ops::Reduce::<U512>::reduce(
226 U512::from_le_byte_array((*bytes).into()),
227 ))
228 }
229}
230
231pub(super) trait BytesModOrder {
234 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self;
235 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self;
236}
237
238#[cfg(feature = "secp256k1")]
239impl BytesModOrder for RustCryptoScalar<k256::Secp256k1> {
240 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
241 crate::utils::scalar_from_be_bytes_mod_order_reducing_32_64(bytes, &Self(k256::Scalar::ONE))
242 }
243 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
244 crate::utils::scalar_from_le_bytes_mod_order_reducing_32_64(bytes, &Self(k256::Scalar::ONE))
245 }
246}
247#[cfg(feature = "secp256r1")]
248impl BytesModOrder for RustCryptoScalar<p256::NistP256> {
249 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
250 crate::utils::scalar_from_be_bytes_mod_order_reducing_32(bytes, &Self(p256::Scalar::ONE))
251 }
252 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
253 crate::utils::scalar_from_le_bytes_mod_order_reducing_32(bytes, &Self(p256::Scalar::ONE))
254 }
255}
256#[cfg(feature = "stark")]
257impl BytesModOrder for RustCryptoScalar<stark_curve::StarkCurve> {
258 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
259 crate::utils::scalar_from_be_bytes_mod_order_reducing_32(
260 bytes,
261 &Self(stark_curve::Scalar::ONE),
262 )
263 }
264 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
265 crate::utils::scalar_from_le_bytes_mod_order_reducing_32(
266 bytes,
267 &Self(stark_curve::Scalar::ONE),
268 )
269 }
270}