generic_ec_curves/rust_crypto/
scalar.rs

1use 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
12/// Scalar wrapper
13pub 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
231/// Choice of algorithm for computing bytes mod curve order. Efficient algorithm
232/// is different for different curves.
233pub(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}