k256/arithmetic/
field.rs

1//! Field arithmetic modulo p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
2
3#![allow(clippy::assign_op_pattern, clippy::op_ref)]
4
5use cfg_if::cfg_if;
6
7cfg_if! {
8    if #[cfg(target_pointer_width = "32")] {
9        mod field_10x26;
10    } else if #[cfg(target_pointer_width = "64")] {
11        mod field_5x52;
12    } else {
13        compile_error!("unsupported target word size (i.e. target_pointer_width)");
14    }
15}
16
17cfg_if! {
18    if #[cfg(debug_assertions)] {
19        mod field_impl;
20        use field_impl::FieldElementImpl;
21    } else {
22        cfg_if! {
23            if #[cfg(target_pointer_width = "32")] {
24                use field_10x26::FieldElement10x26 as FieldElementImpl;
25            } else if #[cfg(target_pointer_width = "64")] {
26                use field_5x52::FieldElement5x52 as FieldElementImpl;
27            } else {
28                compile_error!("unsupported target word size (i.e. target_pointer_width)");
29            }
30        }
31    }
32}
33
34use crate::FieldBytes;
35use core::{
36    iter::{Product, Sum},
37    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
38};
39use elliptic_curve::{
40    ff::{self, Field, PrimeField},
41    ops::Invert,
42    rand_core::RngCore,
43    subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
44    zeroize::DefaultIsZeroes,
45};
46
47#[cfg(test)]
48use num_bigint::{BigUint, ToBigUint};
49
50/// An element in the finite field used for curve coordinates.
51#[derive(Clone, Copy, Debug)]
52pub struct FieldElement(FieldElementImpl);
53
54impl FieldElement {
55    /// Zero element.
56    pub const ZERO: Self = Self(FieldElementImpl::ZERO);
57
58    /// Multiplicative identity.
59    pub const ONE: Self = Self(FieldElementImpl::ONE);
60
61    /// Determine if this `FieldElement` is zero.
62    ///
63    /// # Returns
64    ///
65    /// If zero, return `Choice(1)`.  Otherwise, return `Choice(0)`.
66    pub fn is_zero(&self) -> Choice {
67        self.0.is_zero()
68    }
69
70    /// Determine if this `FieldElement` is even in the SEC1 sense: `self mod 2 == 0`.
71    ///
72    /// # Returns
73    ///
74    /// If even, return `Choice(1)`.  Otherwise, return `Choice(0)`.
75    pub fn is_even(&self) -> Choice {
76        !self.0.is_odd()
77    }
78
79    /// Determine if this `FieldElement` is odd in the SEC1 sense: `self mod 2 == 1`.
80    ///
81    /// # Returns
82    ///
83    /// If odd, return `Choice(1)`.  Otherwise, return `Choice(0)`.
84    pub fn is_odd(&self) -> Choice {
85        self.0.is_odd()
86    }
87
88    /// Attempts to parse the given byte array as an SEC1-encoded field element.
89    /// Does not check the result for being in the correct range.
90    pub(crate) const fn from_bytes_unchecked(bytes: &[u8; 32]) -> Self {
91        Self(FieldElementImpl::from_bytes_unchecked(bytes))
92    }
93
94    /// Attempts to parse the given byte array as an SEC1-encoded field element.
95    ///
96    /// Returns None if the byte array does not contain a big-endian integer in the range
97    /// [0, p).
98    pub fn from_bytes(bytes: &FieldBytes) -> CtOption<Self> {
99        FieldElementImpl::from_bytes(bytes).map(Self)
100    }
101
102    /// Convert a `u64` to a field element.
103    pub const fn from_u64(w: u64) -> Self {
104        Self(FieldElementImpl::from_u64(w))
105    }
106
107    /// Returns the SEC1 encoding of this field element.
108    pub fn to_bytes(self) -> FieldBytes {
109        self.0.normalize().to_bytes()
110    }
111
112    /// Returns -self, treating it as a value of given magnitude.
113    /// The provided magnitude must be equal or greater than the actual magnitude of `self`.
114    pub fn negate(&self, magnitude: u32) -> Self {
115        Self(self.0.negate(magnitude))
116    }
117
118    /// Fully normalizes the field element.
119    /// Brings the magnitude to 1 and modulo reduces the value.
120    pub fn normalize(&self) -> Self {
121        Self(self.0.normalize())
122    }
123
124    /// Weakly normalizes the field element.
125    /// Brings the magnitude to 1, but does not guarantee the value to be less than the modulus.
126    pub fn normalize_weak(&self) -> Self {
127        Self(self.0.normalize_weak())
128    }
129
130    /// Checks if the field element becomes zero if normalized.
131    pub fn normalizes_to_zero(&self) -> Choice {
132        self.0.normalizes_to_zero()
133    }
134
135    /// Multiplies by a single-limb integer.
136    /// Multiplies the magnitude by the same value.
137    pub fn mul_single(&self, rhs: u32) -> Self {
138        Self(self.0.mul_single(rhs))
139    }
140
141    /// Returns 2*self.
142    /// Doubles the magnitude.
143    pub fn double(&self) -> Self {
144        Self(self.0.add(&(self.0)))
145    }
146
147    /// Returns self * rhs mod p
148    /// Brings the magnitude to 1 (but doesn't normalize the result).
149    /// The magnitudes of arguments should be <= 8.
150    pub fn mul(&self, rhs: &Self) -> Self {
151        Self(self.0.mul(&(rhs.0)))
152    }
153
154    /// Returns self * self.
155    ///
156    /// Brings the magnitude to 1 (but doesn't normalize the result).
157    /// The magnitudes of arguments should be <= 8.
158    pub fn square(&self) -> Self {
159        Self(self.0.square())
160    }
161
162    /// Raises the scalar to the power `2^k`
163    fn pow2k(&self, k: usize) -> Self {
164        let mut x = *self;
165        for _j in 0..k {
166            x = x.square();
167        }
168        x
169    }
170
171    /// Returns the multiplicative inverse of self, if self is non-zero.
172    /// The result has magnitude 1, but is not normalized.
173    pub fn invert(&self) -> CtOption<Self> {
174        // The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
175        // { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
176        // [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
177
178        let x2 = self.pow2k(1).mul(self);
179        let x3 = x2.pow2k(1).mul(self);
180        let x6 = x3.pow2k(3).mul(&x3);
181        let x9 = x6.pow2k(3).mul(&x3);
182        let x11 = x9.pow2k(2).mul(&x2);
183        let x22 = x11.pow2k(11).mul(&x11);
184        let x44 = x22.pow2k(22).mul(&x22);
185        let x88 = x44.pow2k(44).mul(&x44);
186        let x176 = x88.pow2k(88).mul(&x88);
187        let x220 = x176.pow2k(44).mul(&x44);
188        let x223 = x220.pow2k(3).mul(&x3);
189
190        // The final result is then assembled using a sliding window over the blocks.
191        let res = x223
192            .pow2k(23)
193            .mul(&x22)
194            .pow2k(5)
195            .mul(self)
196            .pow2k(3)
197            .mul(&x2)
198            .pow2k(2)
199            .mul(self);
200
201        CtOption::new(res, !self.normalizes_to_zero())
202    }
203
204    /// Returns the square root of self mod p, or `None` if no square root exists.
205    /// The result has magnitude 1, but is not normalized.
206    pub fn sqrt(&self) -> CtOption<Self> {
207        /*
208        Given that p is congruent to 3 mod 4, we can compute the square root of
209        a mod p as the (p+1)/4'th power of a.
210
211        As (p+1)/4 is an even number, it will have the same result for a and for
212        (-a). Only one of these two numbers actually has a square root however,
213        so we test at the end by squaring and comparing to the input.
214        Also because (p+1)/4 is an even number, the computed square root is
215        itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
216        */
217
218        // The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
219        // { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
220        // 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
221
222        let x2 = self.pow2k(1).mul(self);
223        let x3 = x2.pow2k(1).mul(self);
224        let x6 = x3.pow2k(3).mul(&x3);
225        let x9 = x6.pow2k(3).mul(&x3);
226        let x11 = x9.pow2k(2).mul(&x2);
227        let x22 = x11.pow2k(11).mul(&x11);
228        let x44 = x22.pow2k(22).mul(&x22);
229        let x88 = x44.pow2k(44).mul(&x44);
230        let x176 = x88.pow2k(88).mul(&x88);
231        let x220 = x176.pow2k(44).mul(&x44);
232        let x223 = x220.pow2k(3).mul(&x3);
233
234        // The final result is then assembled using a sliding window over the blocks.
235        let res = x223.pow2k(23).mul(&x22).pow2k(6).mul(&x2).pow2k(2);
236
237        let is_root = (res.mul(&res).negate(1) + self).normalizes_to_zero();
238
239        // Only return Some if it's the square root.
240        CtOption::new(res, is_root)
241    }
242
243    #[cfg(test)]
244    pub fn modulus_as_biguint() -> BigUint {
245        Self::ONE.negate(1).to_biguint().unwrap() + 1.to_biguint().unwrap()
246    }
247}
248
249impl Invert for FieldElement {
250    type Output = CtOption<Self>;
251
252    fn invert(&self) -> CtOption<Self> {
253        self.invert()
254    }
255}
256
257impl Field for FieldElement {
258    const ZERO: Self = Self::ZERO;
259    const ONE: Self = Self::ONE;
260
261    fn random(mut rng: impl RngCore) -> Self {
262        let mut bytes = FieldBytes::default();
263
264        loop {
265            rng.fill_bytes(&mut bytes);
266            if let Some(fe) = Self::from_bytes(&bytes).into() {
267                return fe;
268            }
269        }
270    }
271
272    #[must_use]
273    fn square(&self) -> Self {
274        self.square()
275    }
276
277    #[must_use]
278    fn double(&self) -> Self {
279        self.double()
280    }
281
282    fn invert(&self) -> CtOption<Self> {
283        self.invert()
284    }
285
286    fn sqrt(&self) -> CtOption<Self> {
287        self.sqrt()
288    }
289
290    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
291        ff::helpers::sqrt_ratio_generic(num, div)
292    }
293}
294
295impl PrimeField for FieldElement {
296    type Repr = FieldBytes;
297
298    const MODULUS: &'static str =
299        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f";
300    const NUM_BITS: u32 = 256;
301    const CAPACITY: u32 = 255;
302    const TWO_INV: Self = Self(FieldElementImpl::from_bytes_unchecked(&[
303        0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
304        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff,
305        0xfe, 0x18,
306    ]));
307    const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(3);
308    const S: u32 = 1;
309    const ROOT_OF_UNITY: Self = Self(FieldElementImpl::from_bytes_unchecked(&[
310        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
311        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
312        0xfc, 0x2e,
313    ]));
314    const ROOT_OF_UNITY_INV: Self = Self(FieldElementImpl::from_bytes_unchecked(&[
315        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
316        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
317        0xfc, 0x2e,
318    ]));
319    const DELTA: Self = Self::from_u64(9);
320
321    fn from_repr(repr: Self::Repr) -> CtOption<Self> {
322        Self::from_bytes(&repr)
323    }
324
325    fn to_repr(&self) -> Self::Repr {
326        self.to_bytes()
327    }
328
329    fn is_odd(&self) -> Choice {
330        self.is_odd()
331    }
332}
333
334impl ConditionallySelectable for FieldElement {
335    #[inline(always)]
336    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
337        Self(FieldElementImpl::conditional_select(&(a.0), &(b.0), choice))
338    }
339}
340
341impl ConstantTimeEq for FieldElement {
342    fn ct_eq(&self, other: &Self) -> Choice {
343        self.0.ct_eq(&(other.0))
344    }
345}
346
347impl Default for FieldElement {
348    fn default() -> Self {
349        Self::ZERO
350    }
351}
352
353impl DefaultIsZeroes for FieldElement {}
354
355impl Eq for FieldElement {}
356
357impl From<u64> for FieldElement {
358    fn from(k: u64) -> Self {
359        Self(FieldElementImpl::from_u64(k))
360    }
361}
362
363impl PartialEq for FieldElement {
364    fn eq(&self, other: &Self) -> bool {
365        self.0.ct_eq(&(other.0)).into()
366    }
367}
368
369impl Add<FieldElement> for FieldElement {
370    type Output = FieldElement;
371
372    fn add(self, other: FieldElement) -> FieldElement {
373        FieldElement(self.0.add(&(other.0)))
374    }
375}
376
377impl Add<&FieldElement> for FieldElement {
378    type Output = FieldElement;
379
380    fn add(self, other: &FieldElement) -> FieldElement {
381        FieldElement(self.0.add(&(other.0)))
382    }
383}
384
385impl Add<&FieldElement> for &FieldElement {
386    type Output = FieldElement;
387
388    fn add(self, other: &FieldElement) -> FieldElement {
389        FieldElement(self.0.add(&(other.0)))
390    }
391}
392
393impl AddAssign<FieldElement> for FieldElement {
394    fn add_assign(&mut self, other: FieldElement) {
395        *self = *self + &other;
396    }
397}
398
399impl AddAssign<&FieldElement> for FieldElement {
400    fn add_assign(&mut self, other: &FieldElement) {
401        *self = *self + other;
402    }
403}
404
405impl Sub<FieldElement> for FieldElement {
406    type Output = FieldElement;
407
408    fn sub(self, other: FieldElement) -> FieldElement {
409        self + -other
410    }
411}
412
413impl Sub<&FieldElement> for FieldElement {
414    type Output = FieldElement;
415
416    fn sub(self, other: &FieldElement) -> FieldElement {
417        self + -other
418    }
419}
420
421impl SubAssign<FieldElement> for FieldElement {
422    fn sub_assign(&mut self, other: FieldElement) {
423        *self = *self + -other;
424    }
425}
426
427impl SubAssign<&FieldElement> for FieldElement {
428    fn sub_assign(&mut self, other: &FieldElement) {
429        *self = *self + -other;
430    }
431}
432
433impl Mul<FieldElement> for FieldElement {
434    type Output = FieldElement;
435
436    fn mul(self, other: FieldElement) -> FieldElement {
437        FieldElement(self.0.mul(&(other.0)))
438    }
439}
440
441impl Mul<&FieldElement> for FieldElement {
442    type Output = FieldElement;
443
444    #[inline(always)]
445    fn mul(self, other: &FieldElement) -> FieldElement {
446        FieldElement(self.0.mul(&(other.0)))
447    }
448}
449
450impl Mul<&FieldElement> for &FieldElement {
451    type Output = FieldElement;
452
453    fn mul(self, other: &FieldElement) -> FieldElement {
454        FieldElement(self.0.mul(&(other.0)))
455    }
456}
457
458impl MulAssign<FieldElement> for FieldElement {
459    fn mul_assign(&mut self, rhs: FieldElement) {
460        *self = *self * &rhs;
461    }
462}
463
464impl MulAssign<&FieldElement> for FieldElement {
465    fn mul_assign(&mut self, rhs: &FieldElement) {
466        *self = *self * rhs;
467    }
468}
469
470impl Neg for FieldElement {
471    type Output = FieldElement;
472
473    fn neg(self) -> FieldElement {
474        self.negate(1)
475    }
476}
477
478impl Neg for &FieldElement {
479    type Output = FieldElement;
480
481    fn neg(self) -> FieldElement {
482        self.negate(1)
483    }
484}
485
486impl Sum for FieldElement {
487    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
488        iter.reduce(core::ops::Add::add).unwrap_or(Self::ZERO)
489    }
490}
491
492impl<'a> Sum<&'a FieldElement> for FieldElement {
493    #[inline]
494    fn sum<I: Iterator<Item = &'a FieldElement>>(iter: I) -> Self {
495        iter.copied().sum()
496    }
497}
498
499impl Product for FieldElement {
500    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
501        iter.reduce(core::ops::Mul::mul).unwrap_or(Self::ONE)
502    }
503}
504
505impl<'a> Product<&'a FieldElement> for FieldElement {
506    fn product<I: Iterator<Item = &'a FieldElement>>(iter: I) -> Self {
507        iter.copied().product()
508    }
509}
510
511#[cfg(test)]
512mod tests {
513    use elliptic_curve::ff::{Field, PrimeField};
514    use elliptic_curve::ops::BatchInvert;
515    use num_bigint::{BigUint, ToBigUint};
516    use proptest::prelude::*;
517    use rand_core::OsRng;
518
519    use super::FieldElement;
520    use crate::{
521        arithmetic::dev::{biguint_to_bytes, bytes_to_biguint},
522        test_vectors::field::DBL_TEST_VECTORS,
523        FieldBytes,
524    };
525
526    #[cfg(feature = "alloc")]
527    use alloc::vec::Vec;
528
529    impl From<&BigUint> for FieldElement {
530        fn from(x: &BigUint) -> Self {
531            let bytes = biguint_to_bytes(x);
532            Self::from_bytes(&bytes.into()).unwrap()
533        }
534    }
535
536    impl ToBigUint for FieldElement {
537        fn to_biguint(&self) -> Option<BigUint> {
538            Some(bytes_to_biguint(self.to_bytes().as_ref()))
539        }
540    }
541
542    /// t = (modulus - 1) >> S
543    const T: [u64; 4] = [
544        0xffffffff7ffffe17,
545        0xffffffffffffffff,
546        0xffffffffffffffff,
547        0x7fffffffffffffff,
548    ];
549
550    #[test]
551    fn two_inv_constant() {
552        assert_eq!(
553            (FieldElement::from(2u64) * FieldElement::TWO_INV).normalize(),
554            FieldElement::ONE
555        );
556    }
557
558    #[test]
559    fn root_of_unity_constant() {
560        // ROOT_OF_UNITY^{2^s} mod m == 1
561        assert_eq!(
562            FieldElement::ROOT_OF_UNITY
563                .pow_vartime(&[1u64 << FieldElement::S, 0, 0, 0])
564                .normalize(),
565            FieldElement::ONE
566        );
567
568        // MULTIPLICATIVE_GENERATOR^{t} mod m == ROOT_OF_UNITY
569        assert_eq!(
570            FieldElement::MULTIPLICATIVE_GENERATOR
571                .pow_vartime(&T)
572                .normalize(),
573            FieldElement::ROOT_OF_UNITY
574        )
575    }
576
577    #[test]
578    fn root_of_unity_inv_constant() {
579        assert_eq!(
580            (FieldElement::ROOT_OF_UNITY * FieldElement::ROOT_OF_UNITY_INV).normalize(),
581            FieldElement::ONE
582        );
583    }
584
585    #[test]
586    fn delta_constant() {
587        // DELTA^{t} mod m == 1
588        assert_eq!(
589            FieldElement::DELTA.pow_vartime(&T).normalize(),
590            FieldElement::ONE
591        );
592    }
593
594    #[test]
595    fn zero_is_additive_identity() {
596        let zero = FieldElement::ZERO;
597        let one = FieldElement::ONE;
598        assert_eq!((zero + &zero).normalize(), zero);
599        assert_eq!((one + &zero).normalize(), one);
600    }
601
602    #[test]
603    fn one_is_multiplicative_identity() {
604        let one = FieldElement::ONE;
605        assert_eq!((one * &one).normalize(), one);
606    }
607
608    #[test]
609    fn from_bytes() {
610        assert_eq!(
611            FieldElement::from_bytes(&FieldBytes::default()).unwrap(),
612            FieldElement::ZERO
613        );
614        assert_eq!(
615            FieldElement::from_bytes(
616                &[
617                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
618                    0, 0, 0, 0, 0, 1
619                ]
620                .into()
621            )
622            .unwrap(),
623            FieldElement::ONE
624        );
625        assert!(bool::from(
626            FieldElement::from_bytes(&[0xff; 32].into()).is_none()
627        ));
628    }
629
630    #[test]
631    fn to_bytes() {
632        assert_eq!(FieldElement::ZERO.to_bytes(), [0; 32].into());
633        assert_eq!(
634            FieldElement::ONE.to_bytes(),
635            [
636                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
637                0, 0, 0, 1
638            ]
639            .into()
640        );
641    }
642
643    #[test]
644    fn repeated_add() {
645        let mut r = FieldElement::ONE;
646        for i in 0..DBL_TEST_VECTORS.len() {
647            assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into());
648            r = (r + &r).normalize();
649        }
650    }
651
652    #[test]
653    fn repeated_double() {
654        let mut r = FieldElement::ONE;
655        for i in 0..DBL_TEST_VECTORS.len() {
656            assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into());
657            r = r.double().normalize();
658        }
659    }
660
661    #[test]
662    fn repeated_mul() {
663        let mut r = FieldElement::ONE;
664        let two = r + &r;
665        for i in 0..DBL_TEST_VECTORS.len() {
666            assert_eq!(r.normalize().to_bytes(), DBL_TEST_VECTORS[i].into());
667            r = r * &two;
668        }
669    }
670
671    #[test]
672    fn negation() {
673        let two = FieldElement::ONE.double();
674        let neg_two = two.negate(2);
675        assert_eq!((two + &neg_two).normalize(), FieldElement::ZERO);
676        assert_eq!(neg_two.negate(3).normalize(), two.normalize());
677    }
678
679    #[test]
680    fn invert() {
681        assert!(bool::from(FieldElement::ZERO.invert().is_none()));
682
683        let one = FieldElement::ONE;
684        assert_eq!(one.invert().unwrap().normalize(), one);
685
686        let two = one + &one;
687        let inv_two = two.invert().unwrap();
688        assert_eq!((two * &inv_two).normalize(), one);
689    }
690
691    #[test]
692    fn batch_invert_array() {
693        let k: FieldElement = FieldElement::random(&mut OsRng);
694        let l: FieldElement = FieldElement::random(&mut OsRng);
695
696        let expected = [k.invert().unwrap(), l.invert().unwrap()];
697        assert_eq!(
698            <FieldElement as BatchInvert<_>>::batch_invert(&[k, l]).unwrap(),
699            expected
700        );
701    }
702
703    #[test]
704    #[cfg(feature = "alloc")]
705    fn batch_invert() {
706        let k: FieldElement = FieldElement::random(&mut OsRng);
707        let l: FieldElement = FieldElement::random(&mut OsRng);
708
709        let expected = vec![k.invert().unwrap(), l.invert().unwrap()];
710        let field_elements = vec![k, l];
711        let res: Vec<_> =
712            <FieldElement as BatchInvert<_>>::batch_invert(field_elements.as_slice()).unwrap();
713        assert_eq!(res, expected);
714    }
715
716    #[test]
717    fn sqrt() {
718        let one = FieldElement::ONE;
719        let two = one + &one;
720        let four = two.square();
721        assert_eq!(four.sqrt().unwrap().normalize(), two.normalize());
722    }
723
724    #[test]
725    #[cfg_attr(
726        debug_assertions,
727        should_panic(expected = "assertion failed: self.normalized")
728    )]
729    fn unnormalized_is_odd() {
730        // This is a regression test for https://github.com/RustCrypto/elliptic-curves/issues/529
731        // where `is_odd()` in debug mode force-normalized its argument
732        // instead of checking that it is already normalized.
733        // As a result, in release (where normalization didn't happen) `is_odd()`
734        // could return an incorrect value.
735
736        let x = FieldElement::from_bytes_unchecked(&[
737            61, 128, 156, 189, 241, 12, 174, 4, 80, 52, 238, 78, 188, 251, 9, 188, 95, 115, 38, 6,
738            212, 168, 175, 174, 211, 232, 208, 14, 182, 45, 59, 122,
739        ]);
740        // Produces an unnormalized FieldElement with magnitude 1
741        // (we cannot create one directly).
742        let y = x.sqrt().unwrap();
743
744        // This is fine.
745        assert!(y.normalize().is_odd().unwrap_u8() == 0);
746
747        // This panics since `y` is not normalized.
748        let _result = y.is_odd();
749    }
750
751    prop_compose! {
752        fn field_element()(bytes in any::<[u8; 32]>()) -> FieldElement {
753            let mut res = bytes_to_biguint(&bytes);
754            let m = FieldElement::modulus_as_biguint();
755            // Modulus is 256 bit long, same as the maximum `res`,
756            // so this is guaranteed to land us in the correct range.
757            if res >= m {
758                res -= m;
759            }
760            FieldElement::from(&res)
761        }
762    }
763
764    proptest! {
765
766        #[test]
767        fn fuzzy_add(
768            a in field_element(),
769            b in field_element()
770        ) {
771            let a_bi = a.to_biguint().unwrap();
772            let b_bi = b.to_biguint().unwrap();
773            let res_bi = (&a_bi + &b_bi) % FieldElement::modulus_as_biguint();
774            let res_ref = FieldElement::from(&res_bi);
775            let res_test = (&a + &b).normalize();
776            assert_eq!(res_test, res_ref);
777        }
778
779        #[test]
780        fn fuzzy_mul(
781            a in field_element(),
782            b in field_element()
783        ) {
784            let a_bi = a.to_biguint().unwrap();
785            let b_bi = b.to_biguint().unwrap();
786            let res_bi = (&a_bi * &b_bi) % FieldElement::modulus_as_biguint();
787            let res_ref = FieldElement::from(&res_bi);
788            let res_test = (&a * &b).normalize();
789            assert_eq!(res_test, res_ref);
790        }
791
792        #[test]
793        fn fuzzy_square(
794            a in field_element()
795        ) {
796            let a_bi = a.to_biguint().unwrap();
797            let res_bi = (&a_bi * &a_bi) % FieldElement::modulus_as_biguint();
798            let res_ref = FieldElement::from(&res_bi);
799            let res_test = a.square().normalize();
800            assert_eq!(res_test, res_ref);
801        }
802
803        #[test]
804        fn fuzzy_negate(
805            a in field_element()
806        ) {
807            let m = FieldElement::modulus_as_biguint();
808            let a_bi = a.to_biguint().unwrap();
809            let res_bi = (&m - &a_bi) % &m;
810            let res_ref = FieldElement::from(&res_bi);
811            let res_test = a.negate(1).normalize();
812            assert_eq!(res_test, res_ref);
813        }
814
815        #[test]
816        fn fuzzy_sqrt(
817            a in field_element()
818        ) {
819            let m = FieldElement::modulus_as_biguint();
820            let a_bi = a.to_biguint().unwrap();
821            let sqr_bi = (&a_bi * &a_bi) % &m;
822            let sqr = FieldElement::from(&sqr_bi);
823
824            let res_ref1 = a;
825            let possible_sqrt = (&m - &a_bi) % &m;
826            let res_ref2 = FieldElement::from(&possible_sqrt);
827            let res_test = sqr.sqrt().unwrap().normalize();
828            // FIXME: is there a rule which square root is returned?
829            assert!(res_test == res_ref1 || res_test == res_ref2);
830        }
831
832        #[test]
833        fn fuzzy_invert(
834            a in field_element()
835        ) {
836            let a = if bool::from(a.is_zero()) { FieldElement::ONE } else { a };
837            let a_bi = a.to_biguint().unwrap();
838            let inv = a.invert().unwrap().normalize();
839            let inv_bi = inv.to_biguint().unwrap();
840            let m = FieldElement::modulus_as_biguint();
841            assert_eq!((&inv_bi * &a_bi) % &m, 1.to_biguint().unwrap());
842        }
843    }
844}