1#![allow(
14 clippy::should_implement_trait,
15 clippy::suspicious_op_assign_impl,
16 clippy::unused_unit,
17 clippy::unnecessary_cast,
18 clippy::too_many_arguments,
19 clippy::identity_op,
20 rustdoc::bare_urls
21)]
22
23#[path = "field/p521_64.rs"]
25mod field_impl;
26mod loose;
27
28pub(crate) use self::loose::LooseFieldElement;
29
30use self::field_impl::*;
31use crate::{FieldBytes, NistP521, U576};
32use core::{
33 fmt::{self, Debug},
34 iter::{Product, Sum},
35 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
36};
37use elliptic_curve::{
38 ff::{self, Field, PrimeField},
39 generic_array::GenericArray,
40 rand_core::RngCore,
41 subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeLess, CtOption},
42 zeroize::DefaultIsZeroes,
43 Error, FieldBytesEncoding,
44};
45
46use super::util::u576_to_le_bytes;
47
48const MODULUS_HEX: &str = "00000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
51
52pub(crate) const MODULUS: U576 = U576::from_be_hex(MODULUS_HEX);
53
54#[derive(Clone, Copy)]
56pub struct FieldElement(pub(crate) fiat_p521_tight_field_element);
57
58impl FieldElement {
59 pub const ZERO: Self = Self::from_u64(0);
61
62 pub const ONE: Self = Self::from_u64(1);
64
65 const BYTES: usize = 66;
67
68 pub fn from_bytes(repr: &FieldBytes) -> CtOption<Self> {
70 let uint = <U576 as FieldBytesEncoding<NistP521>>::decode_field_bytes(repr);
71 Self::from_uint(uint)
72 }
73
74 pub fn from_slice(slice: &[u8]) -> elliptic_curve::Result<Self> {
76 if slice.len() != Self::BYTES {
77 return Err(Error);
78 }
79
80 Option::from(Self::from_bytes(GenericArray::from_slice(slice))).ok_or(Error)
81 }
82
83 pub fn from_uint(uint: U576) -> CtOption<Self> {
85 let is_some = uint.ct_lt(&MODULUS);
86 CtOption::new(Self::from_uint_unchecked(uint), is_some)
87 }
88
89 pub(crate) const fn from_hex(hex: &str) -> Self {
95 Self::from_uint_unchecked(U576::from_be_hex(hex))
96 }
97
98 pub const fn from_u64(w: u64) -> Self {
100 Self::from_uint_unchecked(U576::from_u64(w))
101 }
102
103 pub(crate) const fn from_uint_unchecked(w: U576) -> Self {
109 Self(fiat_p521_from_bytes(&u576_to_le_bytes(w)))
110 }
111
112 pub fn to_bytes(self) -> FieldBytes {
114 let mut ret = fiat_p521_to_bytes(&self.0);
115 ret.reverse();
116 GenericArray::clone_from_slice(&ret)
117 }
118
119 pub fn is_odd(&self) -> Choice {
125 Choice::from(self.0[0] as u8 & 1)
126 }
127
128 pub fn is_even(&self) -> Choice {
134 !self.is_odd()
135 }
136
137 pub fn is_zero(&self) -> Choice {
143 self.ct_eq(&Self::ZERO)
144 }
145
146 #[allow(dead_code)] pub(crate) const fn add_loose(&self, rhs: &Self) -> LooseFieldElement {
149 LooseFieldElement(fiat_p521_add(&self.0, &rhs.0))
150 }
151
152 #[allow(dead_code)] #[must_use]
155 pub(crate) const fn double_loose(&self) -> LooseFieldElement {
156 Self::add_loose(self, self)
157 }
158
159 #[allow(dead_code)] pub(crate) const fn sub_loose(&self, rhs: &Self) -> LooseFieldElement {
162 LooseFieldElement(fiat_p521_sub(&self.0, &rhs.0))
163 }
164
165 #[allow(dead_code)] pub(crate) const fn neg_loose(&self) -> LooseFieldElement {
168 LooseFieldElement(fiat_p521_opp(&self.0))
169 }
170
171 pub const fn add(&self, rhs: &Self) -> Self {
173 Self(fiat_p521_carry_add(&self.0, &rhs.0))
174 }
175
176 pub const fn sub(&self, rhs: &Self) -> Self {
178 Self(fiat_p521_carry_sub(&self.0, &rhs.0))
179 }
180
181 pub const fn neg(&self) -> Self {
183 Self(fiat_p521_carry_opp(&self.0))
184 }
185
186 #[must_use]
188 pub const fn double(&self) -> Self {
189 self.add(self)
190 }
191
192 pub const fn multiply(&self, rhs: &Self) -> Self {
194 LooseFieldElement::mul(&self.relax(), &rhs.relax())
195 }
196
197 pub const fn square(&self) -> Self {
199 self.relax().square()
200 }
201
202 const fn sqn(&self, n: usize) -> Self {
204 let mut x = self.square();
205 let mut i = 1;
206 while i < n {
207 x = x.square();
208 i += 1;
209 }
210 x
211 }
212
213 pub const fn pow_vartime(&self, exp: &[u64]) -> Self {
219 let mut res = Self::ONE;
220 let mut i = exp.len();
221
222 while i > 0 {
223 i -= 1;
224
225 let mut j = 64;
226 while j > 0 {
227 j -= 1;
228 res = res.square();
229
230 if ((exp[i] >> j) & 1) == 1 {
231 res = Self::multiply(&res, self);
232 }
233 }
234 }
235
236 res
237 }
238
239 pub fn invert(&self) -> CtOption<Self> {
241 CtOption::new(self.invert_unchecked(), !self.is_zero())
242 }
243
244 const fn invert_unchecked(&self) -> Self {
248 let z = self.square();
250 let z = self.multiply(&z);
251 let t0 = z.sqn(2);
252 let z = z.multiply(&t0);
253 let t0 = z.sqn(4);
254 let z = z.multiply(&t0);
255 let t0 = z.sqn(8);
256 let z = z.multiply(&t0);
257 let t0 = z.sqn(16);
258 let z = z.multiply(&t0);
259 let t0 = z.sqn(32);
260 let z = z.multiply(&t0);
261 let t0 = z.square();
262 let t0 = self.multiply(&t0);
263 let t0 = t0.sqn(64);
264 let z = z.multiply(&t0);
265 let t0 = z.square();
266 let t0 = self.multiply(&t0);
267 let t0 = t0.sqn(129);
268 let z = z.multiply(&t0);
269 let t0 = z.square();
270 let t0 = self.multiply(&t0);
271 let t0 = t0.sqn(259);
272 let z = z.multiply(&t0);
273 let z = z.sqn(2);
274 self.multiply(&z)
275 }
276
277 pub fn sqrt(&self) -> CtOption<Self> {
289 let sqrt = self.sqn(519);
290 CtOption::new(sqrt, sqrt.square().ct_eq(self))
291 }
292
293 pub(crate) const fn relax(&self) -> LooseFieldElement {
295 LooseFieldElement(fiat_p521_relax(&self.0))
296 }
297}
298
299impl AsRef<fiat_p521_tight_field_element> for FieldElement {
300 fn as_ref(&self) -> &fiat_p521_tight_field_element {
301 &self.0
302 }
303}
304
305impl Default for FieldElement {
306 fn default() -> Self {
307 Self::ZERO
308 }
309}
310
311impl Debug for FieldElement {
312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336 let mut bytes = fiat_p521_to_bytes(&self.0);
337 bytes.reverse();
338
339 let formatter = base16ct::HexDisplay(&bytes);
340 f.debug_tuple("FieldElement")
341 .field(&format_args!("0x{formatter:X}"))
342 .finish()
343 }
344}
345
346impl Eq for FieldElement {}
347impl PartialEq for FieldElement {
348 fn eq(&self, rhs: &Self) -> bool {
349 self.ct_eq(rhs).into()
350 }
351}
352
353impl From<u32> for FieldElement {
354 fn from(n: u32) -> FieldElement {
355 Self::from_uint_unchecked(U576::from(n))
356 }
357}
358
359impl From<u64> for FieldElement {
360 fn from(n: u64) -> FieldElement {
361 Self::from_uint_unchecked(U576::from(n))
362 }
363}
364
365impl From<u128> for FieldElement {
366 fn from(n: u128) -> FieldElement {
367 Self::from_uint_unchecked(U576::from(n))
368 }
369}
370
371impl ConditionallySelectable for FieldElement {
372 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
373 let mut ret = Self::ZERO;
374
375 for i in 0..ret.0.len() {
376 ret.0[i] = u64::conditional_select(&a.0[i], &b.0[i], choice);
377 }
378
379 ret
380 }
381}
382
383impl ConstantTimeEq for FieldElement {
384 fn ct_eq(&self, other: &Self) -> Choice {
385 let a = fiat_p521_to_bytes(&self.0);
386 let b = fiat_p521_to_bytes(&other.0);
387 a.ct_eq(&b)
388 }
389}
390
391impl DefaultIsZeroes for FieldElement {}
392
393impl Field for FieldElement {
394 const ZERO: Self = Self::ZERO;
395 const ONE: Self = Self::ONE;
396
397 fn random(mut rng: impl RngCore) -> Self {
398 let mut bytes = <FieldBytes>::default();
400
401 loop {
402 rng.fill_bytes(&mut bytes);
403 if let Some(fe) = Self::from_bytes(&bytes).into() {
404 return fe;
405 }
406 }
407 }
408
409 fn is_zero(&self) -> Choice {
410 Self::ZERO.ct_eq(self)
411 }
412
413 #[must_use]
414 fn square(&self) -> Self {
415 self.square()
416 }
417
418 #[must_use]
419 fn double(&self) -> Self {
420 self.double()
421 }
422
423 fn invert(&self) -> CtOption<Self> {
424 self.invert()
425 }
426
427 fn sqrt(&self) -> CtOption<Self> {
428 self.sqrt()
429 }
430
431 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
432 ff::helpers::sqrt_ratio_generic(num, div)
433 }
434}
435
436impl PrimeField for FieldElement {
437 type Repr = FieldBytes;
438
439 const MODULUS: &'static str = MODULUS_HEX;
440 const NUM_BITS: u32 = 521;
441 const CAPACITY: u32 = 520;
442 const TWO_INV: Self = Self::from_u64(2).invert_unchecked();
443 const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(3);
444 const S: u32 = 1;
445 const ROOT_OF_UNITY: Self = Self::from_hex("00000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
446 const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
447 const DELTA: Self = Self::from_u64(9);
448
449 #[inline]
450 fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
451 Self::from_bytes(&bytes)
452 }
453
454 #[inline]
455 fn to_repr(&self) -> FieldBytes {
456 self.to_bytes()
457 }
458
459 #[inline]
460 fn is_odd(&self) -> Choice {
461 self.is_odd()
462 }
463}
464
465impl Add for FieldElement {
470 type Output = FieldElement;
471
472 #[inline]
473 fn add(self, rhs: FieldElement) -> FieldElement {
474 Self::add(&self, &rhs)
475 }
476}
477
478impl Add<&FieldElement> for FieldElement {
479 type Output = FieldElement;
480
481 #[inline]
482 fn add(self, rhs: &FieldElement) -> FieldElement {
483 Self::add(&self, rhs)
484 }
485}
486
487impl Add<&FieldElement> for &FieldElement {
488 type Output = FieldElement;
489
490 #[inline]
491 fn add(self, rhs: &FieldElement) -> FieldElement {
492 FieldElement::add(self, rhs)
493 }
494}
495
496impl AddAssign<FieldElement> for FieldElement {
497 #[inline]
498 fn add_assign(&mut self, other: FieldElement) {
499 *self = *self + other;
500 }
501}
502
503impl AddAssign<&FieldElement> for FieldElement {
504 #[inline]
505 fn add_assign(&mut self, other: &FieldElement) {
506 *self = *self + other;
507 }
508}
509
510impl Sub for FieldElement {
511 type Output = FieldElement;
512
513 #[inline]
514 fn sub(self, rhs: FieldElement) -> FieldElement {
515 Self::sub(&self, &rhs)
516 }
517}
518
519impl Sub<&FieldElement> for FieldElement {
520 type Output = FieldElement;
521
522 #[inline]
523 fn sub(self, rhs: &FieldElement) -> FieldElement {
524 Self::sub(&self, rhs)
525 }
526}
527
528impl Sub<&FieldElement> for &FieldElement {
529 type Output = FieldElement;
530
531 #[inline]
532 fn sub(self, rhs: &FieldElement) -> FieldElement {
533 FieldElement::sub(self, rhs)
534 }
535}
536
537impl SubAssign<FieldElement> for FieldElement {
538 #[inline]
539 fn sub_assign(&mut self, other: FieldElement) {
540 *self = *self - other;
541 }
542}
543
544impl SubAssign<&FieldElement> for FieldElement {
545 #[inline]
546 fn sub_assign(&mut self, other: &FieldElement) {
547 *self = *self - other;
548 }
549}
550
551impl Mul for FieldElement {
552 type Output = FieldElement;
553
554 #[inline]
555 fn mul(self, rhs: FieldElement) -> FieldElement {
556 self.relax().mul(&rhs.relax())
557 }
558}
559
560impl Mul<&FieldElement> for FieldElement {
561 type Output = FieldElement;
562
563 #[inline]
564 fn mul(self, rhs: &FieldElement) -> FieldElement {
565 self.relax().mul(&rhs.relax())
566 }
567}
568
569impl Mul<&FieldElement> for &FieldElement {
570 type Output = FieldElement;
571
572 #[inline]
573 fn mul(self, rhs: &FieldElement) -> FieldElement {
574 self.relax().mul(&rhs.relax())
575 }
576}
577
578impl MulAssign<&FieldElement> for FieldElement {
579 #[inline]
580 fn mul_assign(&mut self, other: &FieldElement) {
581 *self = *self * other;
582 }
583}
584
585impl MulAssign for FieldElement {
586 #[inline]
587 fn mul_assign(&mut self, other: FieldElement) {
588 *self = *self * other;
589 }
590}
591
592impl Neg for FieldElement {
593 type Output = FieldElement;
594
595 #[inline]
596 fn neg(self) -> FieldElement {
597 Self::neg(&self)
598 }
599}
600
601impl Sum for FieldElement {
606 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
607 iter.reduce(core::ops::Add::add).unwrap_or(Self::ZERO)
608 }
609}
610
611impl<'a> Sum<&'a FieldElement> for FieldElement {
612 fn sum<I: Iterator<Item = &'a FieldElement>>(iter: I) -> Self {
613 iter.copied().sum()
614 }
615}
616
617impl Product for FieldElement {
618 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
619 iter.reduce(core::ops::Mul::mul).unwrap_or(Self::ONE)
620 }
621}
622
623impl<'a> Product<&'a FieldElement> for FieldElement {
624 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
625 iter.copied().product()
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use super::FieldElement;
632 use elliptic_curve::ff::PrimeField;
633 use hex_literal::hex;
634 use primeorder::{
635 impl_field_identity_tests, impl_field_invert_tests, impl_field_sqrt_tests,
636 impl_primefield_tests,
637 };
638
639 const T: [u64; 9] = [
641 0xffffffffffffffff,
642 0xffffffffffffffff,
643 0xffffffffffffffff,
644 0xffffffffffffffff,
645 0xffffffffffffffff,
646 0xffffffffffffffff,
647 0xffffffffffffffff,
648 0xffffffffffffffff,
649 0x00000000000000ff,
650 ];
651
652 impl_field_identity_tests!(FieldElement);
653 impl_field_invert_tests!(FieldElement);
654 impl_field_sqrt_tests!(FieldElement);
655 impl_primefield_tests!(FieldElement, T);
656
657 #[test]
659 fn decode_invalid_field_element_returns_err() {
660 let overflowing_bytes = hex!("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
661 let ct_option = FieldElement::from_bytes(overflowing_bytes.as_ref().into());
662 assert!(bool::from(ct_option.is_none()));
663 }
664}