Skip to main content

p521/arithmetic/
scalar.rs

1//! secp521r1 scalar field elements.
2//!
3//! Arithmetic implementations are provided by `primefield` and `crypto-bigint`.
4
5use crate::{FieldBytes, NistP521, ORDER_HEX, Uint};
6use elliptic_curve::{
7    Curve as _,
8    bigint::Limb,
9    ff::PrimeField,
10    field,
11    ops::Reduce,
12    scalar::{FromUintUnchecked, IsHigh},
13    subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
14};
15use primeorder::wnaf;
16
17#[cfg(feature = "serde")]
18use {
19    elliptic_curve::ScalarValue,
20    serdect::serde::{Deserialize, Serialize, de, ser},
21};
22
23#[cfg(doc)]
24use core::ops::{Add, Mul, Neg, Sub};
25
26primefield::monty_field_params! {
27    name: ScalarParams,
28    modulus: ORDER_HEX,
29    uint: Uint,
30    byte_order: primefield::ByteOrder::BigEndian,
31    multiplicative_generator: 3,
32    doc: "Montgomery parameters for the NIST P-521 scalar modulus `n`."
33}
34
35primefield::monty_field_element! {
36    name: Scalar,
37    params: ScalarParams,
38    uint: Uint,
39    doc: "Element in the NIST P-521 scalar field modulo `n`."
40}
41
42primefield::monty_field_arithmetic! {
43    name: Scalar,
44    params: ScalarParams,
45    uint: Uint
46}
47
48elliptic_curve::scalar_impls!(NistP521, Scalar);
49
50wnaf::impl_wnaf_size_for_scalar!(Scalar);
51
52impl AsRef<Scalar> for Scalar {
53    fn as_ref(&self) -> &Scalar {
54        self
55    }
56}
57
58impl FromUintUnchecked for Scalar {
59    type Uint = Uint;
60
61    fn from_uint_unchecked(uint: Self::Uint) -> Self {
62        Self::from_uint_unchecked(uint)
63    }
64}
65
66impl IsHigh for Scalar {
67    fn is_high(&self) -> Choice {
68        const MODULUS_SHR1: Uint = NistP521::ORDER.as_ref().shr_vartime(1);
69        self.to_canonical().ct_gt(&MODULUS_SHR1)
70    }
71}
72
73impl Reduce<Uint> for Scalar {
74    fn reduce(w: &Uint) -> Self {
75        let (r, underflow) = w.borrowing_sub(&NistP521::ORDER, Limb::ZERO);
76        let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
77        Self::from_uint_unchecked(Uint::conditional_select(w, &r, !underflow))
78    }
79}
80
81impl Reduce<FieldBytes> for Scalar {
82    #[inline]
83    fn reduce(bytes: &FieldBytes) -> Self {
84        <Self as Reduce<Uint>>::reduce(&field::bytes_to_uint::<NistP521>(bytes))
85    }
86}
87
88#[cfg(feature = "serde")]
89impl Serialize for Scalar {
90    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91    where
92        S: ser::Serializer,
93    {
94        ScalarValue::from(self).serialize(serializer)
95    }
96}
97
98#[cfg(feature = "serde")]
99impl<'de> Deserialize<'de> for Scalar {
100    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
101    where
102        D: de::Deserializer<'de>,
103    {
104        Ok(ScalarValue::deserialize(deserializer)?.into())
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::{Scalar, Uint};
111    use elliptic_curve::ff::PrimeField;
112    primefield::test_primefield!(Scalar, Uint);
113}