Skip to main content

p256/arithmetic/
scalar.rs

1//! Scalar field arithmetic modulo n = 115792089210356248762697446949407573529996955224135760342422259061068512044369
2
3use self::scalar_impl::barrett_reduce;
4use crate::{FieldBytes, NistP256, ORDER_HEX};
5use core::{
6    fmt::{self, Debug},
7    iter::{Product, Sum},
8    ops::{Add, AddAssign, Mul, MulAssign, Neg, Shr, ShrAssign, Sub, SubAssign},
9};
10use elliptic_curve::{
11    Curve, Generate,
12    bigint::{ArrayEncoding, Limb, Odd, U256, Uint, cpubits, modular::Retrieve},
13    ctutils,
14    group::ff::{self, Field, FromUniformBytes, PrimeField},
15    ops::{Invert, Reduce, ReduceNonZero},
16    rand_core::TryRng,
17    scalar::{FromUintUnchecked, IsHigh},
18    subtle::{
19        Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
20        CtOption,
21    },
22    zeroize::DefaultIsZeroes,
23};
24use primefield::{FieldExt, PrimeFieldExt};
25use primeorder::wnaf;
26
27cpubits! {
28    32 => {
29        #[path = "scalar/scalar32.rs"]
30        mod scalar_impl;
31    }
32    64 => {
33        #[path = "scalar/scalar64.rs"]
34        mod scalar_impl;
35    }
36}
37
38#[cfg(feature = "serde")]
39use {
40    elliptic_curve::ScalarValue,
41    serdect::serde::{Deserialize, Serialize, de, ser},
42};
43
44/// Constant representing the modulus
45/// n = FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551
46pub(crate) const MODULUS: Odd<U256> = NistP256::ORDER;
47
48/// `MODULUS / 2`
49const FRAC_MODULUS_2: Scalar = Scalar(MODULUS.as_ref().shr_vartime(1));
50
51#[doc = primefield::monty_field_element_doc!("Scalars are elements in the finite field modulo n.")]
52#[derive(Clone, Copy, Default)]
53pub struct Scalar(pub(crate) U256);
54
55impl Scalar {
56    /// Zero scalar.
57    pub const ZERO: Self = Self(U256::ZERO);
58
59    /// Multiplicative identity.
60    pub const ONE: Self = Self(U256::ONE);
61
62    /// Returns the SEC1 encoding of this scalar.
63    #[must_use]
64    pub fn to_bytes(&self) -> FieldBytes {
65        self.0.to_be_byte_array()
66    }
67
68    /// Returns self + rhs mod n
69    #[must_use]
70    pub const fn add(&self, rhs: &Self) -> Self {
71        Self(self.0.add_mod(&rhs.0, NistP256::ORDER.as_nz_ref()))
72    }
73
74    /// Returns 2*self.
75    #[must_use]
76    pub const fn double(&self) -> Self {
77        self.add(self)
78    }
79
80    /// Returns self - rhs mod n.
81    #[must_use]
82    pub const fn sub(&self, rhs: &Self) -> Self {
83        Self(self.0.sub_mod(&rhs.0, NistP256::ORDER.as_nz_ref()))
84    }
85
86    /// Returns self * rhs mod n
87    #[must_use]
88    pub const fn multiply(&self, rhs: &Self) -> Self {
89        let (lo, hi) = self.0.widening_mul(&rhs.0);
90        Self(barrett_reduce(lo, hi))
91    }
92
93    /// Returns self * self mod n
94    #[must_use]
95    pub const fn square(&self) -> Self {
96        // Schoolbook multiplication.
97        self.multiply(self)
98    }
99
100    /// Right shifts the scalar.
101    ///
102    /// Note: not constant-time with respect to the `shift` parameter.
103    #[must_use]
104    pub const fn shr_vartime(&self, shift: u32) -> Scalar {
105        Self(self.0.unbounded_shr_vartime(shift))
106    }
107
108    /// Compute scalar inversion: `1 / self`.
109    pub fn invert(&self) -> CtOption<Self> {
110        self.0
111            .invert_odd_mod(const { &Odd::from_be_hex(ORDER_HEX) })
112            .map(Self)
113            .into()
114    }
115
116    /// Compute scalar inversion: `1 / self` in variable-time.
117    pub fn invert_vartime(&self) -> CtOption<Self> {
118        self.0
119            .invert_odd_mod_vartime(const { &Odd::from_be_hex(ORDER_HEX) })
120            .map(Self)
121            .into()
122    }
123
124    /// Returns the multiplicative inverse of self.
125    ///
126    /// # Panics
127    /// Will panic in the event `self` is zero
128    const fn invert_unwrap(&self) -> Self {
129        Self(
130            self.0
131                .invert_odd_mod(const { &Odd::from_be_hex(ORDER_HEX) })
132                .expect_copied("input should be non-zero"),
133        )
134    }
135
136    /// Returns `self^exp`, where `exp` is a little-endian integer exponent.
137    ///
138    /// **This operation is variable time with respect to the exponent `exp`.**
139    ///
140    /// If the exponent is fixed, this operation is constant time.
141    #[must_use]
142    pub const fn pow_vartime<const RHS_LIMBS: usize>(&self, exp: &Uint<RHS_LIMBS>) -> Self {
143        let mut res = Self::ONE;
144        let mut i = RHS_LIMBS;
145
146        while i > 0 {
147            i -= 1;
148
149            let mut j = Limb::BITS;
150            while j > 0 {
151                j -= 1;
152                res = res.square();
153
154                if ((exp.as_limbs()[i].0 >> j) & 1) == 1 {
155                    res = res.multiply(self);
156                }
157            }
158        }
159
160        res
161    }
162
163    /// Returns `self^(2^n) mod p`.
164    ///
165    /// **This operation is variable time with respect to the exponent `n`.**
166    ///
167    /// If the exponent is fixed, this operation is constant time.
168    #[must_use]
169    pub const fn sqn_vartime(&self, n: usize) -> Self {
170        let mut x = *self;
171        let mut i = 0;
172        while i < n {
173            x = x.square();
174            i += 1;
175        }
176        x
177    }
178
179    /// Is integer representing equivalence class odd?
180    #[must_use]
181    pub fn is_odd(&self) -> Choice {
182        self.0.is_odd().into()
183    }
184
185    /// Is integer representing equivalence class even?
186    #[must_use]
187    pub fn is_even(&self) -> Choice {
188        !self.is_odd()
189    }
190}
191
192elliptic_curve::scalar_impls!(NistP256, Scalar);
193
194impl AsRef<Scalar> for Scalar {
195    fn as_ref(&self) -> &Scalar {
196        self
197    }
198}
199
200impl Field for Scalar {
201    const ZERO: Self = Self::ZERO;
202    const ONE: Self = Self::ONE;
203
204    fn try_random<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
205        let mut bytes = FieldBytes::default();
206
207        // Generate a uniformly random scalar using rejection sampling,
208        // which produces a uniformly random distribution of scalars.
209        //
210        // This method is not constant time, but should be secure so long as
211        // rejected RNG outputs are unrelated to future ones (which is a
212        // necessary property of a `CryptoRng`).
213        //
214        // With an unbiased RNG, the probability of failing to complete after 4
215        // iterations is vanishingly small.
216        loop {
217            rng.try_fill_bytes(&mut bytes)?;
218            if let Some(scalar) = Scalar::from_repr(bytes).into() {
219                return Ok(scalar);
220            }
221        }
222    }
223
224    fn square(&self) -> Self {
225        Scalar::square(self)
226    }
227
228    fn double(&self) -> Self {
229        self.add(self)
230    }
231
232    fn invert(&self) -> CtOption<Self> {
233        Scalar::invert(self)
234    }
235
236    /// Tonelli-Shank's algorithm for q mod 16 = 1
237    /// <https://eprint.iacr.org/2012/685.pdf> (page 12, algorithm 5)
238    #[allow(clippy::many_single_char_names)]
239    fn sqrt(&self) -> CtOption<Self> {
240        const EXP: U256 =
241            U256::from_be_hex("07fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a");
242
243        // Note: `pow_vartime` is constant-time with respect to `self`
244        let w = self.pow_vartime(&EXP);
245
246        let mut v = Self::S;
247        let mut x = *self * w;
248        let mut b = x * w;
249        let mut z = Self::ROOT_OF_UNITY;
250
251        for max_v in (1..=Self::S).rev() {
252            let mut k = 1;
253            let mut tmp = b.square();
254            let mut j_less_than_v = Choice::from(1);
255
256            for j in 2..max_v {
257                let tmp_is_one = tmp.ct_eq(&Self::ONE);
258                let squared = Self::conditional_select(&tmp, &z, tmp_is_one).square();
259                tmp = Self::conditional_select(&squared, &tmp, tmp_is_one);
260                let new_z = Self::conditional_select(&z, &squared, tmp_is_one);
261                j_less_than_v &= !ConstantTimeEq::ct_eq(&j, &v);
262                k = u32::conditional_select(&j, &k, tmp_is_one);
263                z = Self::conditional_select(&z, &new_z, j_less_than_v);
264            }
265
266            let result = x * z;
267            x = Self::conditional_select(&result, &x, b.ct_eq(&Self::ONE));
268            z = z.square();
269            b *= z;
270            v = k;
271        }
272
273        CtOption::new(x, x.square().ct_eq(self))
274    }
275
276    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
277        ff::helpers::sqrt_ratio_generic(num, div)
278    }
279}
280
281impl Generate for Scalar {
282    fn try_generate_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
283        Self::try_random(rng)
284    }
285}
286
287impl PrimeField for Scalar {
288    type Repr = FieldBytes;
289
290    const MODULUS: &'static str = ORDER_HEX;
291    const NUM_BITS: u32 = 256;
292    const CAPACITY: u32 = 255;
293    const TWO_INV: Self = Self(U256::from_u8(2)).invert_unwrap();
294    const MULTIPLICATIVE_GENERATOR: Self = Self(U256::from_u8(7));
295    const S: u32 = 4;
296    const ROOT_OF_UNITY: Self = Self(U256::from_be_hex(
297        "ffc97f062a770992ba807ace842a3dfc1546cad004378daf0592d7fbb41e6602",
298    ));
299    const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unwrap();
300    const DELTA: Self = Self(U256::from_u64(33232930569601));
301
302    /// Attempts to parse the given byte array as an SEC1-encoded scalar.
303    ///
304    /// Returns None if the byte array does not contain a big-endian integer in the range
305    /// [0, p).
306    fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
307        let inner = U256::from_be_byte_array(bytes);
308        CtOption::new(
309            Self(inner),
310            ConstantTimeLess::ct_lt(&inner, &NistP256::ORDER),
311        )
312    }
313
314    fn to_repr(&self) -> FieldBytes {
315        self.to_bytes()
316    }
317
318    fn is_odd(&self) -> Choice {
319        self.0.is_odd().into()
320    }
321}
322
323impl FieldExt for Scalar {}
324impl PrimeFieldExt for Scalar {}
325
326wnaf::impl_wnaf_size_for_scalar!(Scalar);
327
328impl Retrieve for Scalar {
329    type Output = U256;
330
331    fn retrieve(&self) -> U256 {
332        self.0
333    }
334}
335
336impl DefaultIsZeroes for Scalar {}
337
338impl Eq for Scalar {}
339
340impl FromUintUnchecked for Scalar {
341    type Uint = U256;
342
343    fn from_uint_unchecked(uint: Self::Uint) -> Self {
344        Self(uint)
345    }
346}
347
348impl Invert for Scalar {
349    type Output = CtOption<Self>;
350
351    fn invert(&self) -> CtOption<Self> {
352        self.invert()
353    }
354
355    fn invert_vartime(&self) -> CtOption<Self> {
356        self.invert_vartime()
357    }
358}
359
360impl IsHigh for Scalar {
361    fn is_high(&self) -> Choice {
362        ConstantTimeGreater::ct_gt(&self.0, &FRAC_MODULUS_2.0)
363    }
364}
365
366impl Shr<usize> for Scalar {
367    type Output = Self;
368
369    #[allow(clippy::cast_possible_truncation, reason = "TODO")]
370    fn shr(self, rhs: usize) -> Self::Output {
371        self.shr_vartime(rhs as u32)
372    }
373}
374
375impl Shr<usize> for &Scalar {
376    type Output = Scalar;
377
378    #[allow(clippy::cast_possible_truncation, reason = "TODO")]
379    fn shr(self, rhs: usize) -> Self::Output {
380        self.shr_vartime(rhs as u32)
381    }
382}
383
384impl ShrAssign<usize> for Scalar {
385    fn shr_assign(&mut self, rhs: usize) {
386        *self = *self >> rhs;
387    }
388}
389
390impl PartialEq for Scalar {
391    fn eq(&self, other: &Self) -> bool {
392        self.ct_eq(other).into()
393    }
394}
395
396impl PartialOrd for Scalar {
397    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
398        Some(self.cmp(other))
399    }
400}
401
402impl Ord for Scalar {
403    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
404        self.0.cmp(&other.0)
405    }
406}
407
408impl From<u32> for Scalar {
409    fn from(k: u32) -> Self {
410        Scalar(k.into())
411    }
412}
413
414impl From<u64> for Scalar {
415    fn from(k: u64) -> Self {
416        Scalar(k.into())
417    }
418}
419
420impl From<u128> for Scalar {
421    fn from(k: u128) -> Self {
422        Scalar(k.into())
423    }
424}
425
426impl From<Scalar> for FieldBytes {
427    fn from(scalar: Scalar) -> Self {
428        scalar.to_bytes()
429    }
430}
431
432impl From<&Scalar> for FieldBytes {
433    fn from(scalar: &Scalar) -> Self {
434        scalar.to_bytes()
435    }
436}
437
438impl From<Scalar> for U256 {
439    fn from(scalar: Scalar) -> U256 {
440        scalar.0
441    }
442}
443
444impl From<&Scalar> for U256 {
445    fn from(scalar: &Scalar) -> U256 {
446        scalar.0
447    }
448}
449
450impl FromUniformBytes<64> for Scalar {
451    fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
452        Self(barrett_reduce(
453            U256::from_be_slice(&bytes[32..]),
454            U256::from_be_slice(&bytes[..32]),
455        ))
456    }
457}
458
459impl Add<Scalar> for Scalar {
460    type Output = Scalar;
461
462    fn add(self, other: Scalar) -> Scalar {
463        Scalar::add(&self, &other)
464    }
465}
466
467impl Add<&Scalar> for &Scalar {
468    type Output = Scalar;
469
470    fn add(self, other: &Scalar) -> Scalar {
471        Scalar::add(self, other)
472    }
473}
474
475impl Add<&Scalar> for Scalar {
476    type Output = Scalar;
477
478    fn add(self, other: &Scalar) -> Scalar {
479        Scalar::add(&self, other)
480    }
481}
482
483impl AddAssign<Scalar> for Scalar {
484    fn add_assign(&mut self, rhs: Scalar) {
485        *self = Scalar::add(self, &rhs);
486    }
487}
488
489impl AddAssign<&Scalar> for Scalar {
490    fn add_assign(&mut self, rhs: &Scalar) {
491        *self = Scalar::add(self, rhs);
492    }
493}
494
495impl Sub<Scalar> for Scalar {
496    type Output = Scalar;
497
498    fn sub(self, other: Scalar) -> Scalar {
499        Scalar::sub(&self, &other)
500    }
501}
502
503impl Sub<&Scalar> for &Scalar {
504    type Output = Scalar;
505
506    fn sub(self, other: &Scalar) -> Scalar {
507        Scalar::sub(self, other)
508    }
509}
510
511impl Sub<&Scalar> for Scalar {
512    type Output = Scalar;
513
514    fn sub(self, other: &Scalar) -> Scalar {
515        Scalar::sub(&self, other)
516    }
517}
518
519impl SubAssign<Scalar> for Scalar {
520    fn sub_assign(&mut self, rhs: Scalar) {
521        *self = Scalar::sub(self, &rhs);
522    }
523}
524
525impl SubAssign<&Scalar> for Scalar {
526    fn sub_assign(&mut self, rhs: &Scalar) {
527        *self = Scalar::sub(self, rhs);
528    }
529}
530
531impl Mul<Scalar> for Scalar {
532    type Output = Scalar;
533
534    fn mul(self, other: Scalar) -> Scalar {
535        Scalar::multiply(&self, &other)
536    }
537}
538
539impl Mul<&Scalar> for &Scalar {
540    type Output = Scalar;
541
542    fn mul(self, other: &Scalar) -> Scalar {
543        Scalar::multiply(self, other)
544    }
545}
546
547impl Mul<&Scalar> for Scalar {
548    type Output = Scalar;
549
550    fn mul(self, other: &Scalar) -> Scalar {
551        Scalar::multiply(&self, other)
552    }
553}
554
555impl MulAssign<Scalar> for Scalar {
556    fn mul_assign(&mut self, rhs: Scalar) {
557        *self = Scalar::multiply(self, &rhs);
558    }
559}
560
561impl MulAssign<&Scalar> for Scalar {
562    fn mul_assign(&mut self, rhs: &Scalar) {
563        *self = Scalar::multiply(self, rhs);
564    }
565}
566
567impl Neg for Scalar {
568    type Output = Scalar;
569
570    fn neg(self) -> Scalar {
571        Scalar::ZERO - self
572    }
573}
574
575impl Neg for &Scalar {
576    type Output = Scalar;
577
578    fn neg(self) -> Scalar {
579        Scalar::ZERO - self
580    }
581}
582
583impl Reduce<U256> for Scalar {
584    fn reduce(w: &U256) -> Self {
585        let (r, underflow) = w.borrowing_sub(&NistP256::ORDER, Limb::ZERO);
586        let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
587        Self(U256::conditional_select(w, &r, !underflow))
588    }
589}
590
591impl Reduce<FieldBytes> for Scalar {
592    #[inline]
593    fn reduce(bytes: &FieldBytes) -> Self {
594        Self::reduce(&U256::from_be_byte_array(*bytes))
595    }
596}
597
598impl ReduceNonZero<U256> for Scalar {
599    fn reduce_nonzero(w: &U256) -> Self {
600        const ORDER_MINUS_ONE: U256 = NistP256::ORDER.as_ref().wrapping_sub(&U256::ONE);
601        let (r, underflow) = w.borrowing_sub(&ORDER_MINUS_ONE, Limb::ZERO);
602        let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
603        Self(U256::conditional_select(w, &r, !underflow).wrapping_add(&U256::ONE))
604    }
605}
606
607impl ReduceNonZero<FieldBytes> for Scalar {
608    #[inline]
609    fn reduce_nonzero(bytes: &FieldBytes) -> Self {
610        Self::reduce_nonzero(&U256::from_be_byte_array(*bytes))
611    }
612}
613
614impl Sum for Scalar {
615    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
616        iter.reduce(Add::add).unwrap_or(Self::ZERO)
617    }
618}
619
620impl<'a> Sum<&'a Scalar> for Scalar {
621    fn sum<I: Iterator<Item = &'a Scalar>>(iter: I) -> Self {
622        iter.copied().sum()
623    }
624}
625
626impl Product for Scalar {
627    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
628        iter.reduce(Mul::mul).unwrap_or(Self::ONE)
629    }
630}
631
632impl<'a> Product<&'a Scalar> for Scalar {
633    fn product<I: Iterator<Item = &'a Scalar>>(iter: I) -> Self {
634        iter.copied().product()
635    }
636}
637
638impl ConditionallySelectable for Scalar {
639    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
640        Self(U256::conditional_select(&a.0, &b.0, choice))
641    }
642}
643
644impl ConstantTimeEq for Scalar {
645    fn ct_eq(&self, other: &Self) -> Choice {
646        ConstantTimeEq::ct_eq(&self.0, &other.0)
647    }
648}
649
650impl ctutils::CtEq for Scalar {
651    fn ct_eq(&self, other: &Self) -> ctutils::Choice {
652        ConstantTimeEq::ct_eq(self, other).into()
653    }
654}
655
656impl ctutils::CtSelect for Scalar {
657    fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
658        ConditionallySelectable::conditional_select(self, other, choice.into())
659    }
660}
661
662impl Debug for Scalar {
663    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664        write!(f, "Scalar(0x{:X})", &self.0)
665    }
666}
667
668#[cfg(feature = "serde")]
669impl Serialize for Scalar {
670    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
671    where
672        S: ser::Serializer,
673    {
674        ScalarValue::from(self).serialize(serializer)
675    }
676}
677
678#[cfg(feature = "serde")]
679impl<'de> Deserialize<'de> for Scalar {
680    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
681    where
682        D: de::Deserializer<'de>,
683    {
684        Ok(ScalarValue::deserialize(deserializer)?.into())
685    }
686}
687
688#[cfg(test)]
689mod tests {
690    use super::{Scalar, U256};
691    use crate::{FieldBytes, NistP256, SecretKey};
692    use elliptic_curve::{Curve, array::Array, group::ff::PrimeField, ops::ReduceNonZero};
693
694    primefield::test_primefield!(Scalar, U256);
695
696    #[test]
697    fn from_to_bytes_roundtrip() {
698        let k: u64 = 42;
699        let mut bytes = FieldBytes::default();
700        bytes[24..].copy_from_slice(k.to_be_bytes().as_ref());
701
702        let scalar = Scalar::from_repr(bytes).unwrap();
703        assert_eq!(bytes, scalar.to_bytes());
704    }
705
706    /// Basic tests that multiplication works.
707    #[test]
708    fn multiply() {
709        let one = Scalar::ONE;
710        let two = one + one;
711        let three = two + one;
712        let six = three + three;
713        assert_eq!(six, two * three);
714
715        let minus_two = -two;
716        let minus_three = -three;
717        assert_eq!(two, -minus_two);
718
719        assert_eq!(minus_three * minus_two, minus_two * minus_three);
720        assert_eq!(six, minus_two * minus_three);
721    }
722
723    /// Tests that a Scalar can be safely converted to a SecretKey and back
724    #[test]
725    fn from_ec_secret() {
726        let scalar = Scalar::ONE;
727        let secret = SecretKey::from_bytes(&scalar.to_bytes()).unwrap();
728        let rederived_scalar = Scalar::from(&secret);
729        assert_eq!(scalar.0, rederived_scalar.0);
730    }
731
732    #[test]
733    fn reduce_nonzero() {
734        assert_eq!(Scalar::reduce_nonzero(&Array::default()).0, U256::ONE,);
735        assert_eq!(Scalar::reduce_nonzero(&U256::ONE).0, U256::from_u8(2),);
736        assert_eq!(
737            Scalar::reduce_nonzero(&U256::from_u8(2)).0,
738            U256::from_u8(3),
739        );
740
741        assert_eq!(
742            Scalar::reduce_nonzero(NistP256::ORDER.as_ref()).0,
743            U256::from_u8(2),
744        );
745        assert_eq!(
746            Scalar::reduce_nonzero(&NistP256::ORDER.wrapping_sub(&U256::from_u8(1))).0,
747            U256::ONE,
748        );
749        assert_eq!(
750            Scalar::reduce_nonzero(&NistP256::ORDER.wrapping_sub(&U256::from_u8(2))).0,
751            NistP256::ORDER.wrapping_sub(&U256::ONE),
752        );
753        assert_eq!(
754            Scalar::reduce_nonzero(&NistP256::ORDER.wrapping_sub(&U256::from_u8(3))).0,
755            NistP256::ORDER.wrapping_sub(&U256::from_u8(2)),
756        );
757
758        assert_eq!(
759            Scalar::reduce_nonzero(&NistP256::ORDER.wrapping_add(&U256::ONE)).0,
760            U256::from_u8(3),
761        );
762        assert_eq!(
763            Scalar::reduce_nonzero(&NistP256::ORDER.wrapping_add(&U256::from_u8(2))).0,
764            U256::from_u8(4),
765        );
766    }
767}