generic_ec_curves/rust_crypto/
scalar.rs1use core::ops::Mul;
2
3use elliptic_curve::bigint::{ArrayEncoding, ByteArray, U256, U384, U512};
4use elliptic_curve::{Curve, CurveArithmetic, Field, Group, ScalarPrimitive};
5use generic_ec_core::{
6 Additive, CurveGenerator, FromUniformBytes, IntegerEncoding, Invertible, Multiplicative, One,
7 Reduce, SamplableVartime, 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
87#[cfg(feature = "secp256k1")]
88impl FromUniformBytes for RustCryptoScalar<k256::Secp256k1> {
89 type Bytes = [u8; 48];
94 fn from_uniform_bytes(bytes: &Self::Bytes) -> Self {
95 let mut bytes_be = [0u8; 64];
96 bytes_be[64 - 48..].copy_from_slice(bytes);
97 <Self as Reduce<64>>::from_be_array_mod_order(&bytes_be)
98 }
99}
100#[cfg(feature = "secp256r1")]
101impl FromUniformBytes for RustCryptoScalar<p256::NistP256> {
102 type Bytes = [u8; 48];
107 fn from_uniform_bytes(bytes: &Self::Bytes) -> Self {
108 BytesModOrder::from_be_bytes_mod_order(bytes)
109 }
110}
111#[cfg(feature = "secp384r1")]
112impl FromUniformBytes for RustCryptoScalar<p384::NistP384> {
113 type Bytes = [u8; 64];
118 fn from_uniform_bytes(bytes: &Self::Bytes) -> Self {
119 BytesModOrder::from_be_bytes_mod_order(bytes)
120 }
121}
122#[cfg(feature = "stark")]
123impl FromUniformBytes for RustCryptoScalar<stark_curve::StarkCurve> {
124 type Bytes = [u8; 48];
129 fn from_uniform_bytes(bytes: &Self::Bytes) -> Self {
130 BytesModOrder::from_be_bytes_mod_order(bytes)
131 }
132}
133
134impl<E: CurveArithmetic> SamplableVartime for RustCryptoScalar<E> {
135 fn random_vartime(rng: &mut impl rand_core::RngCore) -> Self {
136 use elliptic_curve::PrimeField;
137
138 let mut bytes: <E::Scalar as PrimeField>::Repr = Default::default();
139 loop {
140 rng.fill_bytes(bytes.as_mut());
141
142 if let Some(scalar) = <E::Scalar as PrimeField>::from_repr_vartime(bytes.clone()) {
143 break Self(scalar);
144 }
145 }
146 }
147}
148
149impl<E: CurveArithmetic> Default for RustCryptoScalar<E> {
150 fn default() -> Self {
151 Self(Default::default())
152 }
153}
154
155impl<E: CurveArithmetic> Clone for RustCryptoScalar<E> {
156 fn clone(&self) -> Self {
157 *self
158 }
159}
160
161impl<E: CurveArithmetic> Copy for RustCryptoScalar<E> {}
162
163impl<E> DefaultIsZeroes for RustCryptoScalar<E>
164where
165 E: CurveArithmetic,
166 E::Scalar: DefaultIsZeroes,
167{
168}
169
170impl<E> PartialEq for RustCryptoScalar<E>
171where
172 E: CurveArithmetic,
173 E::Scalar: PartialEq,
174{
175 fn eq(&self, other: &Self) -> bool {
176 self.0 == other.0
177 }
178}
179
180impl<E> Eq for RustCryptoScalar<E>
181where
182 E: CurveArithmetic,
183 E::Scalar: Eq,
184{
185}
186
187impl<E> ConstantTimeEq for RustCryptoScalar<E>
188where
189 E: CurveArithmetic,
190 E::Scalar: ConstantTimeEq,
191{
192 fn ct_eq(&self, other: &Self) -> Choice {
193 self.0.ct_eq(&other.0)
194 }
195}
196
197impl<E> ConditionallySelectable for RustCryptoScalar<E>
198where
199 E: CurveArithmetic,
200 E::Scalar: ConditionallySelectable,
201{
202 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
203 Self(E::Scalar::conditional_select(&a.0, &b.0, choice))
204 }
205}
206
207impl<E: CurveArithmetic + Curve> IntegerEncoding for RustCryptoScalar<E>
208where
209 for<'s> ScalarPrimitive<E>: From<&'s E::Scalar>,
210 E::Scalar: elliptic_curve::ops::Reduce<E::Uint>,
211 Self: BytesModOrder,
212{
213 type Bytes = ByteArray<E::Uint>;
214
215 fn to_be_bytes(&self) -> Self::Bytes {
216 let scalar_core = ScalarPrimitive::<E>::from(&self.0);
217 let uint = scalar_core.as_uint();
218 uint.to_be_byte_array()
219 }
220
221 fn to_le_bytes(&self) -> Self::Bytes {
222 let scalar_core = ScalarPrimitive::<E>::from(&self.0);
223 let uint = scalar_core.as_uint();
224 uint.to_le_byte_array()
225 }
226
227 fn from_be_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
228 let uint = E::Uint::from_be_byte_array(bytes.clone());
229 let scalar_core: Option<ScalarPrimitive<E>> = ScalarPrimitive::<E>::new(uint).into();
230 Some(Self(E::Scalar::from(scalar_core?)))
231 }
232
233 fn from_le_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
234 let uint = E::Uint::from_le_byte_array(bytes.clone());
235 let scalar_core: Option<ScalarPrimitive<E>> = ScalarPrimitive::<E>::new(uint).into();
236 Some(Self(E::Scalar::from(scalar_core?)))
237 }
238
239 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
240 <Self as BytesModOrder>::from_be_bytes_mod_order(bytes)
241 }
242 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
243 <Self as BytesModOrder>::from_le_bytes_mod_order(bytes)
244 }
245}
246
247impl<E: CurveArithmetic + Curve> Reduce<32> for RustCryptoScalar<E>
248where
249 E::Scalar: elliptic_curve::ops::Reduce<U256>,
250{
251 fn from_be_array_mod_order(bytes: &[u8; 32]) -> Self {
252 Self(elliptic_curve::ops::Reduce::<U256>::reduce(
253 U256::from_be_byte_array((*bytes).into()),
254 ))
255 }
256 fn from_le_array_mod_order(bytes: &[u8; 32]) -> Self {
257 Self(elliptic_curve::ops::Reduce::<U256>::reduce(
258 U256::from_le_byte_array((*bytes).into()),
259 ))
260 }
261}
262
263impl<E: CurveArithmetic + Curve> Reduce<64> for RustCryptoScalar<E>
264where
265 E::Scalar: elliptic_curve::ops::Reduce<U512>,
266{
267 fn from_be_array_mod_order(bytes: &[u8; 64]) -> Self {
268 Self(elliptic_curve::ops::Reduce::<U512>::reduce(
269 U512::from_be_byte_array((*bytes).into()),
270 ))
271 }
272 fn from_le_array_mod_order(bytes: &[u8; 64]) -> Self {
273 Self(elliptic_curve::ops::Reduce::<U512>::reduce(
274 U512::from_le_byte_array((*bytes).into()),
275 ))
276 }
277}
278
279impl<E: CurveArithmetic + Curve> Reduce<48> for RustCryptoScalar<E>
280where
281 E::Scalar: elliptic_curve::ops::Reduce<U384>,
282{
283 fn from_be_array_mod_order(bytes: &[u8; 48]) -> Self {
284 Self(elliptic_curve::ops::Reduce::<U384>::reduce(
285 U384::from_be_byte_array((*bytes).into()),
286 ))
287 }
288 fn from_le_array_mod_order(bytes: &[u8; 48]) -> Self {
289 Self(elliptic_curve::ops::Reduce::<U384>::reduce(
290 U384::from_le_byte_array((*bytes).into()),
291 ))
292 }
293}
294
295pub(super) trait BytesModOrder {
298 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self;
299 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self;
300}
301
302#[cfg(feature = "secp256k1")]
303impl BytesModOrder for RustCryptoScalar<k256::Secp256k1> {
304 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
305 crate::utils::scalar_from_be_bytes_mod_order_reducing_32_64(bytes, &Self(k256::Scalar::ONE))
306 }
307 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
308 crate::utils::scalar_from_le_bytes_mod_order_reducing_32_64(bytes, &Self(k256::Scalar::ONE))
309 }
310}
311#[cfg(feature = "secp256r1")]
312impl BytesModOrder for RustCryptoScalar<p256::NistP256> {
313 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
314 crate::utils::scalar_from_be_bytes_mod_order_reducing::<_, 32>(
315 bytes,
316 &Self(p256::Scalar::ONE),
317 )
318 }
319 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
320 crate::utils::scalar_from_le_bytes_mod_order_reducing::<_, 32>(
321 bytes,
322 &Self(p256::Scalar::ONE),
323 )
324 }
325}
326#[cfg(feature = "secp384r1")]
327impl BytesModOrder for RustCryptoScalar<p384::NistP384> {
328 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
329 crate::utils::scalar_from_be_bytes_mod_order_reducing::<_, 48>(
330 bytes,
331 &Self(p384::Scalar::ONE),
332 )
333 }
334 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
335 crate::utils::scalar_from_le_bytes_mod_order_reducing::<_, 48>(
336 bytes,
337 &Self(p384::Scalar::ONE),
338 )
339 }
340}
341#[cfg(feature = "stark")]
342impl BytesModOrder for RustCryptoScalar<stark_curve::StarkCurve> {
343 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
344 crate::utils::scalar_from_be_bytes_mod_order_reducing::<_, 32>(
345 bytes,
346 &Self(stark_curve::Scalar::ONE),
347 )
348 }
349 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
350 crate::utils::scalar_from_le_bytes_mod_order_reducing::<_, 32>(
351 bytes,
352 &Self(stark_curve::Scalar::ONE),
353 )
354 }
355}