Skip to main content

generic_ec_curves/rust_crypto/
scalar.rs

1use 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
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
87#[cfg(feature = "secp256k1")]
88impl FromUniformBytes for RustCryptoScalar<k256::Secp256k1> {
89    /// 48 bytes
90    ///
91    /// `L = ceil((ceil(log2(q)) + k) / 8) = ceil((256 + 128) / 8) = 48` bytes are enough to
92    /// guarantee the uniform distribution
93    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    /// 48 bytes
103    ///
104    /// `L = ceil((ceil(log2(q)) + k) / 8) = ceil((256 + 128) / 8) = 48` bytes are enough to
105    /// guarantee the uniform distribution
106    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    /// 64 bytes
114    ///
115    /// `L = ceil((ceil(log2(q)) + k) / 8) = ceil((384 + 128) / 8) = 64` bytes are enough to
116    /// guarantee the uniform distribution
117    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    /// 48 bytes
125    ///
126    /// `L = ceil((ceil(log2(q)) + k) / 8) = ceil((256 + 128) / 8) = 48` bytes are enough to
127    /// guarantee the uniform distribution
128    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
295/// Choice of algorithm for computing bytes mod curve order. Efficient algorithm
296/// is different for different curves.
297pub(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}