Skip to main content

elliptic_curve/scalar/
value.rs

1//!  Integer values within the range of a given [`Curve`]'s scalar modulus.
2
3use crate::{
4    Curve, Error, FieldBytes, Result,
5    array::Array,
6    bigint::{AddMod, ConstOne, ConstZero, Integer, Limb, NegMod, Odd, RandomMod, SubMod, Zero},
7    ctutils::{self, CtEq, CtGt, CtLt, CtSelect},
8    field,
9    scalar::{FromUintUnchecked, IsHigh},
10};
11use base16ct::HexDisplay;
12use common::Generate;
13use core::{
14    cmp::Ordering,
15    fmt,
16    ops::{Add, AddAssign, Neg, ShrAssign, Sub, SubAssign},
17    str,
18};
19use rand_core::{CryptoRng, TryCryptoRng};
20use subtle::{
21    Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
22    CtOption,
23};
24use zeroize::DefaultIsZeroes;
25
26#[cfg(feature = "arithmetic")]
27use super::{CurveArithmetic, Scalar};
28
29#[cfg(feature = "serde")]
30use serdect::serde::{Deserialize, Serialize, de, ser};
31
32/// Integer values within the range of a given [`Curve`]'s scalar modulus.
33///
34/// This type provides a baseline level of scalar arithmetic functionality
35/// which is always available for all curves.
36///
37/// # `serde` support
38///
39/// When the optional `serde` feature of this create is enabled, [`Serialize`]
40/// and [`Deserialize`] impls are provided for this type.
41///
42/// The serialization is a fixed-width big endian encoding. When used with
43/// textual formats, the binary data is encoded as hexadecimal.
44// TODO(tarcieri): replace with `primefield`? RustCrypto/elliptic-curves#1192
45#[derive(Copy, Clone, Debug, Default)]
46pub struct ScalarValue<C: Curve> {
47    /// Inner unsigned integer type.
48    inner: C::Uint,
49}
50
51impl<C> ScalarValue<C>
52where
53    C: Curve,
54{
55    /// Zero scalar.
56    pub const ZERO: Self = Self {
57        inner: C::Uint::ZERO,
58    };
59
60    /// Multiplicative identity.
61    pub const ONE: Self = Self {
62        inner: C::Uint::ONE,
63    };
64
65    /// Scalar modulus.
66    pub const MODULUS: Odd<C::Uint> = C::ORDER;
67
68    /// Create a new scalar from [`Curve::Uint`].
69    pub fn new(uint: C::Uint) -> CtOption<Self> {
70        CtOption::new(
71            Self { inner: uint },
72            CtLt::ct_lt(&uint, &Self::MODULUS).into(),
73        )
74    }
75
76    /// Decode [`ScalarValue`] from a serialized field element
77    pub fn from_bytes(bytes: &FieldBytes<C>) -> CtOption<Self> {
78        Self::new(field::bytes_to_uint::<C>(bytes))
79    }
80
81    /// Decode [`ScalarValue`] from a big endian byte slice.
82    ///
83    /// # Errors
84    /// - if `slice` is not sized appropriately for [`Self::MODULUS`].
85    /// - if the decoded scalar field element overflows [`Self::MODULUS`].
86    pub fn from_slice(slice: &[u8]) -> Result<Self> {
87        let bytes = Array::try_from(slice).map_err(|_| Error)?;
88        Self::from_bytes(&bytes).into_option().ok_or(Error)
89    }
90
91    /// Borrow the inner `C::Uint`.
92    pub fn as_uint(&self) -> &C::Uint {
93        &self.inner
94    }
95
96    /// Borrow the inner limbs as a slice.
97    pub fn as_limbs(&self) -> &[Limb] {
98        self.inner.as_ref()
99    }
100
101    /// Is this [`ScalarValue`] value equal to zero?
102    pub fn is_zero(&self) -> Choice {
103        self.inner.is_zero().into()
104    }
105
106    /// Is this [`ScalarValue`] value even?
107    pub fn is_even(&self) -> Choice {
108        self.inner.is_even().into()
109    }
110
111    /// Is this [`ScalarValue`] value odd?
112    pub fn is_odd(&self) -> Choice {
113        self.inner.is_odd().into()
114    }
115
116    /// Encode [`ScalarValue`] as a serialized field element.
117    pub fn to_bytes(&self) -> FieldBytes<C> {
118        field::uint_to_bytes::<C>(&self.inner)
119    }
120
121    /// Convert to a `C::Uint`.
122    pub fn to_uint(&self) -> C::Uint {
123        self.inner
124    }
125
126    /// Deprecated: Generate a random [`ScalarValue`].
127    #[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
128    pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
129        Self::generate_from_rng(rng)
130    }
131}
132
133impl<C> From<u64> for ScalarValue<C>
134where
135    C: Curve,
136{
137    fn from(n: u64) -> Self {
138        Self {
139            inner: C::Uint::from(n),
140        }
141    }
142}
143
144impl<C> FromUintUnchecked for ScalarValue<C>
145where
146    C: Curve,
147{
148    type Uint = C::Uint;
149
150    fn from_uint_unchecked(uint: C::Uint) -> Self {
151        Self { inner: uint }
152    }
153}
154
155impl<C> Generate for ScalarValue<C>
156where
157    C: Curve,
158{
159    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
160        rng: &mut R,
161    ) -> core::result::Result<Self, R::Error> {
162        Ok(Self {
163            inner: C::Uint::try_random_mod_vartime(rng, Self::MODULUS.as_nz_ref())?,
164        })
165    }
166}
167
168#[cfg(feature = "arithmetic")]
169impl<C> ScalarValue<C>
170where
171    C: CurveArithmetic,
172{
173    /// Convert [`ScalarValue`] into a given curve's scalar type.
174    pub(super) fn to_scalar(self) -> Scalar<C> {
175        Scalar::<C>::from_uint_unchecked(self.inner)
176    }
177}
178
179// TODO(tarcieri): better encapsulate this?
180impl<C> AsRef<[Limb]> for ScalarValue<C>
181where
182    C: Curve,
183{
184    fn as_ref(&self) -> &[Limb] {
185        self.as_limbs()
186    }
187}
188
189impl<C> ConditionallySelectable for ScalarValue<C>
190where
191    C: Curve,
192{
193    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
194        Self {
195            inner: C::Uint::ct_select(&a.inner, &b.inner, choice.into()),
196        }
197    }
198}
199
200impl<C> ConstantTimeEq for ScalarValue<C>
201where
202    C: Curve,
203{
204    fn ct_eq(&self, other: &Self) -> Choice {
205        self.inner.ct_eq(&other.inner).into()
206    }
207}
208
209impl<C> ConstantTimeLess for ScalarValue<C>
210where
211    C: Curve,
212{
213    fn ct_lt(&self, other: &Self) -> Choice {
214        self.inner.ct_lt(&other.inner).into()
215    }
216}
217
218impl<C> ConstantTimeGreater for ScalarValue<C>
219where
220    C: Curve,
221{
222    fn ct_gt(&self, other: &Self) -> Choice {
223        self.inner.ct_gt(&other.inner).into()
224    }
225}
226
227impl<C> CtSelect for ScalarValue<C>
228where
229    C: Curve,
230{
231    fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
232        Self {
233            inner: C::Uint::ct_select(&self.inner, &other.inner, choice),
234        }
235    }
236}
237
238impl<C> CtEq for ScalarValue<C>
239where
240    C: Curve,
241{
242    fn ct_eq(&self, other: &Self) -> ctutils::Choice {
243        self.inner.ct_eq(&other.inner)
244    }
245}
246
247impl<C> CtGt for ScalarValue<C>
248where
249    C: Curve,
250{
251    fn ct_gt(&self, other: &Self) -> ctutils::Choice {
252        self.inner.ct_gt(&other.inner)
253    }
254}
255
256impl<C> CtLt for ScalarValue<C>
257where
258    C: Curve,
259{
260    fn ct_lt(&self, other: &Self) -> ctutils::Choice {
261        self.inner.ct_lt(&other.inner)
262    }
263}
264
265impl<C: Curve> DefaultIsZeroes for ScalarValue<C> {}
266
267impl<C: Curve> Eq for ScalarValue<C> {}
268
269impl<C> PartialEq for ScalarValue<C>
270where
271    C: Curve,
272{
273    fn eq(&self, other: &Self) -> bool {
274        CtEq::ct_eq(self, other).to_bool()
275    }
276}
277
278impl<C> PartialOrd for ScalarValue<C>
279where
280    C: Curve,
281{
282    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
283        Some(self.cmp(other))
284    }
285}
286
287impl<C> Ord for ScalarValue<C>
288where
289    C: Curve,
290{
291    fn cmp(&self, other: &Self) -> Ordering {
292        self.inner.cmp(&other.inner)
293    }
294}
295
296impl<C> Add<ScalarValue<C>> for ScalarValue<C>
297where
298    C: Curve,
299{
300    type Output = Self;
301
302    fn add(self, other: Self) -> Self {
303        self.add(&other)
304    }
305}
306
307impl<C> Add<&ScalarValue<C>> for ScalarValue<C>
308where
309    C: Curve,
310{
311    type Output = Self;
312
313    fn add(self, other: &Self) -> Self {
314        Self {
315            inner: self.inner.add_mod(&other.inner, Self::MODULUS.as_nz_ref()),
316        }
317    }
318}
319
320impl<C> AddAssign<ScalarValue<C>> for ScalarValue<C>
321where
322    C: Curve,
323{
324    fn add_assign(&mut self, other: Self) {
325        *self = *self + other;
326    }
327}
328
329impl<C> AddAssign<&ScalarValue<C>> for ScalarValue<C>
330where
331    C: Curve,
332{
333    fn add_assign(&mut self, other: &Self) {
334        *self = *self + other;
335    }
336}
337
338impl<C> Sub<ScalarValue<C>> for ScalarValue<C>
339where
340    C: Curve,
341{
342    type Output = Self;
343
344    fn sub(self, other: Self) -> Self {
345        self.sub(&other)
346    }
347}
348
349impl<C> Sub<&ScalarValue<C>> for ScalarValue<C>
350where
351    C: Curve,
352{
353    type Output = Self;
354
355    fn sub(self, other: &Self) -> Self {
356        Self {
357            inner: self.inner.sub_mod(&other.inner, Self::MODULUS.as_nz_ref()),
358        }
359    }
360}
361
362impl<C> SubAssign<ScalarValue<C>> for ScalarValue<C>
363where
364    C: Curve,
365{
366    fn sub_assign(&mut self, other: Self) {
367        *self = *self - other;
368    }
369}
370
371impl<C> SubAssign<&ScalarValue<C>> for ScalarValue<C>
372where
373    C: Curve,
374{
375    fn sub_assign(&mut self, other: &Self) {
376        *self = *self - other;
377    }
378}
379
380impl<C> Neg for ScalarValue<C>
381where
382    C: Curve,
383{
384    type Output = Self;
385
386    fn neg(self) -> Self {
387        Self {
388            inner: self.inner.neg_mod(Self::MODULUS.as_nz_ref()),
389        }
390    }
391}
392
393impl<C> Neg for &ScalarValue<C>
394where
395    C: Curve,
396{
397    type Output = ScalarValue<C>;
398
399    fn neg(self) -> ScalarValue<C> {
400        -*self
401    }
402}
403
404impl<C> ShrAssign<usize> for ScalarValue<C>
405where
406    C: Curve,
407{
408    fn shr_assign(&mut self, rhs: usize) {
409        self.inner >>= rhs;
410    }
411}
412
413impl<C> IsHigh for ScalarValue<C>
414where
415    C: Curve,
416{
417    fn is_high(&self) -> Choice {
418        let n_2 = Self::MODULUS.get() >> 1u32;
419        self.inner.ct_gt(&n_2).into()
420    }
421}
422
423impl<C> fmt::Display for ScalarValue<C>
424where
425    C: Curve,
426{
427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428        write!(f, "{self:X}")
429    }
430}
431
432impl<C> fmt::LowerHex for ScalarValue<C>
433where
434    C: Curve,
435{
436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437        write!(f, "{:x}", HexDisplay(&self.to_bytes()))
438    }
439}
440
441impl<C> fmt::UpperHex for ScalarValue<C>
442where
443    C: Curve,
444{
445    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446        write!(f, "{:X}", HexDisplay(&self.to_bytes()))
447    }
448}
449
450impl<C> str::FromStr for ScalarValue<C>
451where
452    C: Curve,
453{
454    type Err = Error;
455
456    fn from_str(hex: &str) -> Result<Self> {
457        let mut bytes = FieldBytes::<C>::default();
458        base16ct::mixed::decode(hex, &mut bytes)?;
459        Self::from_bytes(&bytes).into_option().ok_or(Error)
460    }
461}
462
463#[cfg(feature = "serde")]
464impl<C> Serialize for ScalarValue<C>
465where
466    C: Curve,
467{
468    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
469    where
470        S: ser::Serializer,
471    {
472        serdect::array::serialize_hex_upper_or_bin(&self.to_bytes(), serializer)
473    }
474}
475
476#[cfg(feature = "serde")]
477impl<'de, C> Deserialize<'de> for ScalarValue<C>
478where
479    C: Curve,
480{
481    fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
482    where
483        D: de::Deserializer<'de>,
484    {
485        let mut bytes = FieldBytes::<C>::default();
486        serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
487        Self::from_bytes(&bytes)
488            .into_option()
489            .ok_or_else(|| de::Error::custom("scalar out of range"))
490    }
491}