1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//! A `FieldElement` represents an element of the finite field //! modulo `2^252 + 27742317777372353535851937790883648493`. //! //! The `FieldElement` type is an alias for one of the backend //! implementations. //! //! `ConstantTimeEq` and `PartialEq` traits have been implemented //! here since they will be the samme across all of the different backends. //! //! # Examples //! ```rust //! use zerocaf::field::FieldElement; //! use zerocaf::traits::ops::*; //! use zerocaf::constants::EDWARDS_D; //! use subtle::Choice; //! //! // You can create a FieldElement from a byte-array as follows: //! let a = FieldElement::from_bytes(&[0u8;32]); //! //! // You ca also create a FieldElement from an uint type as follows: //! let b = FieldElement::from(&86649u128); //! let c = FieldElement::from(&86650u64); //! //! // You can create random FieldElements by calling: //! let rand = FieldElement::generate_random(); //! //! // The last way of creating a FieldElement it by calling the //! // constructor. THIS IS NOT RECOMMENDED since NO checks about //! // the correctness of the input will be done at all. //! // It can be done as follows: //! let d: FieldElement = FieldElement([0, 1, 0, 0, 0]); // d = 2^52. //! assert!(d == FieldElement::two_pow_k(&52u64)); //! //! // All of the basuc modular operations are implemented //! // for FieldElement type: //! let mut res = &a + &b; // Performs a + b (mod l). //! res = a - b; // Performs a - b (mod l). //! res = a * b; // Performs a * b (mod l). //! res = a.square(); // Performs a^2 (mod l). //! res = -&a; // Performs Negation over the modulo l. //! res = a.pow(&b); // Performs Modular exponentiation. //! res = a.mod_sqrt(Choice::from(1u8)).unwrap(); //Performs //! // modular sqrt. //! // Returs `None` if the input is not a QR on the field. //! // Returns Some(result) if everything is correct. //! //! // Division has been also implemented. Remember that when we write //! // a/b (mod l), we are indeed performing a * inverse_mod(b, l) (mod l). //! assert!(-&(b / c) == EDWARDS_D); //! //! // Dividing by two even FieldElements is recommended through the `Half` //! // trait implmementation since it's much faster. //! if a.is_even() { //! let half_a = &a.half(); // This will panic if a isn't even. //! }; //! //! // We can finally perform inversion modulo l for a FieldElement: //! let inv_a = &c.inverse(); // Performs a^-1 (mod l). //! //! // You can export your `FieldElement` as an slice of 32 bytes in Little //! // Endian encoding by: //! let c_bytes: [u8; 32] = c.to_bytes(); //! ``` //! //! `PartialOrd`, `Ord`, `PartialEq` and `Eq` are also implemented for //! `FieldElement` type. //! //! All `std::core::ops traits -> (Add, Sub, Mul, Div)` are implemented //! for both, `&FieldElement` and `FieldElement`. use core::cmp::PartialEq; use subtle::{Choice, ConstantTimeEq, ConditionallySelectable}; use crate::backend; #[cfg(feature = "u64_backend")] pub use backend::u64::field::*; /// A `FieldElement` represents an element of the field /// `2^252 + 27742317777372353535851937790883648493` /// /// The `FieldElement` type is an alias for one of the platform-specific /// implementations. #[cfg(feature = "u64_backend")] pub type FieldElement = backend::u64::field::FieldElement; impl PartialEq for FieldElement { fn eq(&self, other: &FieldElement) -> bool { self.ct_eq(other).unwrap_u8() == 1u8 } } impl ConstantTimeEq for FieldElement { /// Test equality between two `FieldElement`s. Since the /// internal representation is not canonical, the field elements /// are normalized to wire format before comparison. fn ct_eq(&self, other: &FieldElement) -> Choice { self.to_bytes().ct_eq(&other.to_bytes()) } } impl ConditionallySelectable for FieldElement { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { FieldElement([ u64::conditional_select(&a.0[0], &b.0[0], choice), u64::conditional_select(&a.0[1], &b.0[1], choice), u64::conditional_select(&a.0[2], &b.0[2], choice), u64::conditional_select(&a.0[3], &b.0[3], choice), u64::conditional_select(&a.0[4], &b.0[4], choice) ]) } }