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