summaryrefslogtreecommitdiffstats
path: root/vendor/ff/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:42 +0000
commit837b550238aa671a591ccf282dddeab29cadb206 (patch)
tree914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/ff/src
parentAdding debian version 1.70.0+dfsg2-1. (diff)
downloadrustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz
rustc-837b550238aa671a591ccf282dddeab29cadb206.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ff/src')
-rw-r--r--vendor/ff/src/batch.rs18
-rw-r--r--vendor/ff/src/helpers.rs128
-rw-r--r--vendor/ff/src/lib.rs256
3 files changed, 365 insertions, 37 deletions
diff --git a/vendor/ff/src/batch.rs b/vendor/ff/src/batch.rs
index c479f9d49..96ddc5a97 100644
--- a/vendor/ff/src/batch.rs
+++ b/vendor/ff/src/batch.rs
@@ -31,19 +31,19 @@ where
I: IntoIterator<Item = &'a mut F>,
{
fn batch_invert(self) -> F {
- let mut acc = F::one();
+ let mut acc = F::ONE;
let iter = self.into_iter();
let mut tmp = alloc::vec::Vec::with_capacity(iter.size_hint().0);
for p in iter {
let q = *p;
tmp.push((acc, p));
- acc = F::conditional_select(&(acc * q), &acc, q.ct_eq(&F::zero()));
+ acc = F::conditional_select(&(acc * q), &acc, q.is_zero());
}
acc = acc.invert().unwrap();
let allinv = acc;
for (tmp, p) in tmp.into_iter().rev() {
- let skip = p.ct_eq(&F::zero());
+ let skip = p.is_zero();
let tmp = tmp * acc;
acc = F::conditional_select(&(acc * *p), &acc, skip);
@@ -74,17 +74,17 @@ impl BatchInverter {
{
assert_eq!(elements.len(), scratch_space.len());
- let mut acc = F::one();
+ let mut acc = F::ONE;
for (p, scratch) in elements.iter().zip(scratch_space.iter_mut()) {
*scratch = acc;
- acc = F::conditional_select(&(acc * *p), &acc, p.ct_eq(&F::zero()));
+ acc = F::conditional_select(&(acc * *p), &acc, p.is_zero());
}
acc = acc.invert().unwrap();
let allinv = acc;
for (p, scratch) in elements.iter_mut().zip(scratch_space.iter()).rev() {
let tmp = *scratch * acc;
- let skip = p.ct_eq(&F::zero());
+ let skip = p.is_zero();
acc = F::conditional_select(&(acc * *p), &acc, skip);
*p = F::conditional_select(&tmp, &p, skip);
}
@@ -109,11 +109,11 @@ impl BatchInverter {
TE: Fn(&mut T) -> &mut F,
TS: Fn(&mut T) -> &mut F,
{
- let mut acc = F::one();
+ let mut acc = F::ONE;
for item in items.iter_mut() {
*(scratch_space)(item) = acc;
let p = (element)(item);
- acc = F::conditional_select(&(acc * *p), &acc, p.ct_eq(&F::zero()));
+ acc = F::conditional_select(&(acc * *p), &acc, p.is_zero());
}
acc = acc.invert().unwrap();
let allinv = acc;
@@ -121,7 +121,7 @@ impl BatchInverter {
for item in items.iter_mut().rev() {
let tmp = *(scratch_space)(item) * acc;
let p = (element)(item);
- let skip = p.ct_eq(&F::zero());
+ let skip = p.is_zero();
acc = F::conditional_select(&(acc * *p), &acc, skip);
*p = F::conditional_select(&tmp, &p, skip);
}
diff --git a/vendor/ff/src/helpers.rs b/vendor/ff/src/helpers.rs
new file mode 100644
index 000000000..d1d6371dd
--- /dev/null
+++ b/vendor/ff/src/helpers.rs
@@ -0,0 +1,128 @@
+//! Helper methods for implementing the `ff` traits.
+
+use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
+
+use crate::PrimeField;
+
+/// Constant-time implementation of Tonelli–Shanks' square-root algorithm for
+/// `p mod 16 = 1`.
+///
+/// `tm1d2` should be set to `(t - 1) // 2`, where `t = (modulus - 1) >> F::S`.
+///
+/// ## Implementing [`Field::sqrt`]
+///
+/// This function can be used to implement [`Field::sqrt`] for fields that both implement
+/// [`PrimeField`] and satisfy `p mod 16 = 1`.
+///
+/// [`Field::sqrt`]: crate::Field::sqrt
+pub fn sqrt_tonelli_shanks<F: PrimeField, S: AsRef<[u64]>>(f: &F, tm1d2: S) -> CtOption<F> {
+ // This is a constant-time version of https://eprint.iacr.org/2012/685.pdf (page 12,
+ // algorithm 5). Steps 2-5 of the algorithm are omitted because they are only needed
+ // to detect non-square input; it is more efficient to do that by checking at the end
+ // whether the square of the result is the input.
+
+ // w = self^((t - 1) // 2)
+ let w = f.pow_vartime(tm1d2);
+
+ let mut v = F::S;
+ let mut x = w * f;
+ let mut b = x * w;
+
+ // Initialize z as the 2^S root of unity.
+ let mut z = F::ROOT_OF_UNITY;
+
+ for max_v in (1..=F::S).rev() {
+ let mut k = 1;
+ let mut b2k = b.square();
+ let mut j_less_than_v: Choice = 1.into();
+
+ // This loop has three phases based on the value of k for algorithm 5:
+ // - for j <= k, we square b2k in order to calculate b^{2^k}.
+ // - for k < j <= v, we square z in order to calculate ω.
+ // - for j > v, we do nothing.
+ for j in 2..max_v {
+ let b2k_is_one = b2k.ct_eq(&F::ONE);
+ let squared = F::conditional_select(&b2k, &z, b2k_is_one).square();
+ b2k = F::conditional_select(&squared, &b2k, b2k_is_one);
+ let new_z = F::conditional_select(&z, &squared, b2k_is_one);
+ j_less_than_v &= !j.ct_eq(&v);
+ k = u32::conditional_select(&j, &k, b2k_is_one);
+ z = F::conditional_select(&z, &new_z, j_less_than_v);
+ }
+
+ let result = x * z;
+ x = F::conditional_select(&result, &x, b.ct_eq(&F::ONE));
+ z = z.square();
+ b *= z;
+ v = k;
+ }
+
+ CtOption::new(
+ x,
+ (x * x).ct_eq(f), // Only return Some if it's the square root.
+ )
+}
+
+/// Computes:
+///
+/// - $(\textsf{true}, \sqrt{\textsf{num}/\textsf{div}})$, if $\textsf{num}$ and
+/// $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is a square in the
+/// field;
+/// - $(\textsf{true}, 0)$, if $\textsf{num}$ is zero;
+/// - $(\textsf{false}, 0)$, if $\textsf{num}$ is nonzero and $\textsf{div}$ is zero;
+/// - $(\textsf{false}, \sqrt{G_S \cdot \textsf{num}/\textsf{div}})$, if
+/// $\textsf{num}$ and $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is
+/// a nonsquare in the field;
+///
+/// where $G_S$ is a non-square.
+///
+/// For this method, $G_S$ is currently [`PrimeField::ROOT_OF_UNITY`], a generator of the
+/// order $2^S$ subgroup. Users of this crate should not rely on this generator being
+/// fixed; it may be changed in future crate versions to simplify the implementation of
+/// the SSWU hash-to-curve algorithm.
+///
+/// The choice of root from sqrt is unspecified.
+///
+/// ## Implementing [`Field::sqrt_ratio`]
+///
+/// This function can be used to implement [`Field::sqrt_ratio`] for fields that also
+/// implement [`PrimeField`]. If doing so, the default implementation of [`Field::sqrt`]
+/// *MUST* be overridden, or else both functions will recurse in a cycle until a stack
+/// overflow occurs.
+///
+/// [`Field::sqrt_ratio`]: crate::Field::sqrt_ratio
+/// [`Field::sqrt`]: crate::Field::sqrt
+pub fn sqrt_ratio_generic<F: PrimeField>(num: &F, div: &F) -> (Choice, F) {
+ // General implementation:
+ //
+ // a = num * inv0(div)
+ // = { 0 if div is zero
+ // { num/div otherwise
+ //
+ // b = G_S * a
+ // = { 0 if div is zero
+ // { G_S*num/div otherwise
+ //
+ // Since G_S is non-square, a and b are either both zero (and both square), or
+ // only one of them is square. We can therefore choose the square root to return
+ // based on whether a is square, but for the boolean output we need to handle the
+ // num != 0 && div == 0 case specifically.
+
+ let a = div.invert().unwrap_or(F::ZERO) * num;
+ let b = a * F::ROOT_OF_UNITY;
+ let sqrt_a = a.sqrt();
+ let sqrt_b = b.sqrt();
+
+ let num_is_zero = num.is_zero();
+ let div_is_zero = div.is_zero();
+ let is_square = sqrt_a.is_some();
+ let is_nonsquare = sqrt_b.is_some();
+ assert!(bool::from(
+ num_is_zero | div_is_zero | (is_square ^ is_nonsquare)
+ ));
+
+ (
+ is_square & (num_is_zero | !div_is_zero),
+ CtOption::conditional_select(&sqrt_b, &sqrt_a, is_square).unwrap(),
+ )
+}
diff --git a/vendor/ff/src/lib.rs b/vendor/ff/src/lib.rs
index 4ccd0de87..96bd3e966 100644
--- a/vendor/ff/src/lib.rs
+++ b/vendor/ff/src/lib.rs
@@ -12,6 +12,8 @@ extern crate alloc;
mod batch;
pub use batch::*;
+pub mod helpers;
+
#[cfg(feature = "derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub use ff_derive::PrimeField;
@@ -22,8 +24,11 @@ pub use bitvec::view::BitViewSized;
#[cfg(feature = "bits")]
use bitvec::{array::BitArray, order::Lsb0};
+
use core::fmt;
+use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
+
use rand_core::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
@@ -45,32 +50,36 @@ pub trait Field:
+ 'static
+ ConditionallySelectable
+ ConstantTimeEq
+ + Neg<Output = Self>
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
- + Neg<Output = Self>
+ + Sum
+ + Product
+ for<'a> Add<&'a Self, Output = Self>
- + for<'a> Mul<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
- + MulAssign
+ + for<'a> Mul<&'a Self, Output = Self>
+ + for<'a> Sum<&'a Self>
+ + for<'a> Product<&'a Self>
+ AddAssign
+ SubAssign
- + for<'a> MulAssign<&'a Self>
+ + MulAssign
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
+ + for<'a> MulAssign<&'a Self>
{
- /// Returns an element chosen uniformly at random using a user-provided RNG.
- fn random(rng: impl RngCore) -> Self;
+ /// The zero element of the field, the additive identity.
+ const ZERO: Self;
- /// Returns the zero element of the field, the additive identity.
- fn zero() -> Self;
+ /// The one element of the field, the multiplicative identity.
+ const ONE: Self;
- /// Returns the one element of the field, the multiplicative identity.
- fn one() -> Self;
+ /// Returns an element chosen uniformly at random using a user-provided RNG.
+ fn random(rng: impl RngCore) -> Self;
/// Returns true iff this element is zero.
fn is_zero(&self) -> Choice {
- self.ct_eq(&Self::zero())
+ self.ct_eq(&Self::ZERO)
}
/// Returns true iff this element is zero.
@@ -101,17 +110,73 @@ pub trait Field:
/// failing if the element is zero.
fn invert(&self) -> CtOption<Self>;
+ /// Computes:
+ ///
+ /// - $(\textsf{true}, \sqrt{\textsf{num}/\textsf{div}})$, if $\textsf{num}$ and
+ /// $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is a square in the
+ /// field;
+ /// - $(\textsf{true}, 0)$, if $\textsf{num}$ is zero;
+ /// - $(\textsf{false}, 0)$, if $\textsf{num}$ is nonzero and $\textsf{div}$ is zero;
+ /// - $(\textsf{false}, \sqrt{G_S \cdot \textsf{num}/\textsf{div}})$, if
+ /// $\textsf{num}$ and $\textsf{div}$ are nonzero and $\textsf{num}/\textsf{div}$ is
+ /// a nonsquare in the field;
+ ///
+ /// where $G_S$ is a non-square.
+ ///
+ /// # Warnings
+ ///
+ /// - The choice of root from `sqrt` is unspecified.
+ /// - The value of $G_S$ is unspecified, and cannot be assumed to have any specific
+ /// value in a generic context.
+ fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self);
+
+ /// Equivalent to `Self::sqrt_ratio(self, one())`.
+ ///
+ /// The provided method is implemented in terms of [`Self::sqrt_ratio`].
+ fn sqrt_alt(&self) -> (Choice, Self) {
+ Self::sqrt_ratio(self, &Self::ONE)
+ }
+
/// Returns the square root of the field element, if it is
/// quadratic residue.
- fn sqrt(&self) -> CtOption<Self>;
+ ///
+ /// The provided method is implemented in terms of [`Self::sqrt_ratio`].
+ fn sqrt(&self) -> CtOption<Self> {
+ let (is_square, res) = Self::sqrt_ratio(self, &Self::ONE);
+ CtOption::new(res, is_square)
+ }
+
+ /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer
+ /// exponent.
+ ///
+ /// # Guarantees
+ ///
+ /// This operation is constant time with respect to `self`, for all exponents with the
+ /// same number of digits (`exp.as_ref().len()`). It is variable time with respect to
+ /// the number of digits in the exponent.
+ fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
+ let mut res = Self::ONE;
+ for e in exp.as_ref().iter().rev() {
+ for i in (0..64).rev() {
+ res = res.square();
+ let mut tmp = res;
+ tmp *= self;
+ res.conditional_assign(&tmp, (((*e >> i) & 1) as u8).into());
+ }
+ }
+ res
+ }
- /// Exponentiates `self` by `exp`, where `exp` is a little-endian order
- /// integer exponent.
+ /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer
+ /// exponent.
///
- /// **This operation is variable time with respect to the exponent.** If the
- /// exponent is fixed, this operation is effectively constant time.
+ /// # Guarantees
+ ///
+ /// **This operation is variable time with respect to `self`, for all exponent.** If
+ /// the exponent is fixed, this operation is effectively constant time. However, for
+ /// stronger constant-time guarantees, [`Field::pow`] should be used.
fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
- let mut res = Self::one();
+ let mut res = Self::ONE;
for e in exp.as_ref().iter().rev() {
for i in (0..64).rev() {
res = res.square();
@@ -126,7 +191,7 @@ pub trait Field:
}
}
-/// This represents an element of a prime field.
+/// This represents an element of a non-binary prime field.
pub trait PrimeField: Field + From<u64> {
/// The prime field can be converted back and forth into this binary
/// representation.
@@ -144,10 +209,10 @@ pub trait PrimeField: Field + From<u64> {
}
if s == "0" {
- return Some(Self::zero());
+ return Some(Self::ZERO);
}
- let mut res = Self::zero();
+ let mut res = Self::ZERO;
let ten = Self::from(10);
@@ -176,6 +241,26 @@ pub trait PrimeField: Field + From<u64> {
Some(res)
}
+ /// Obtains a field element congruent to the integer `v`.
+ ///
+ /// For fields where `Self::CAPACITY >= 128`, this is injective and will produce a
+ /// unique field element.
+ ///
+ /// For fields where `Self::CAPACITY < 128`, this is surjective; some field elements
+ /// will be produced by multiple values of `v`.
+ ///
+ /// If you want to deterministically sample a field element representing a value, use
+ /// [`FromUniformBytes`] instead.
+ fn from_u128(v: u128) -> Self {
+ let lower = v as u64;
+ let upper = (v >> 64) as u64;
+ let mut tmp = Self::from(upper);
+ for _ in 0..64 {
+ tmp = tmp.double();
+ }
+ tmp + Self::from(lower)
+ }
+
/// Attempts to convert a byte representation of a field element into an element of
/// this prime field, failing if the input is not canonical (is not smaller than the
/// field's modulus).
@@ -215,6 +300,12 @@ pub trait PrimeField: Field + From<u64> {
!self.is_odd()
}
+ /// Modulus of the field written as a string for debugging purposes.
+ ///
+ /// The encoding of the modulus is implementation-specific. Generic users of the
+ /// `PrimeField` trait should treat this string as opaque.
+ const MODULUS: &'static str;
+
/// How many bits are needed to represent an element of this field.
const NUM_BITS: u32;
@@ -223,16 +314,19 @@ pub trait PrimeField: Field + From<u64> {
/// This is usually `Self::NUM_BITS - 1`.
const CAPACITY: u32;
- /// Returns a fixed multiplicative generator of `modulus - 1` order. This element must
- /// also be a quadratic nonresidue.
+ /// Inverse of $2$ in the field.
+ const TWO_INV: Self;
+
+ /// A fixed multiplicative generator of `modulus - 1` order. This element must also be
+ /// a quadratic nonresidue.
///
/// It can be calculated using [SageMath] as `GF(modulus).primitive_element()`.
///
- /// Implementations of this method MUST ensure that this is the generator used to
- /// derive `Self::root_of_unity`.
+ /// Implementations of this trait MUST ensure that this is the generator used to
+ /// derive `Self::ROOT_OF_UNITY`.
///
/// [SageMath]: https://www.sagemath.org/
- fn multiplicative_generator() -> Self;
+ const MULTIPLICATIVE_GENERATOR: Self;
/// An integer `s` satisfying the equation `2^s * t = modulus - 1` with `t` odd.
///
@@ -240,11 +334,117 @@ pub trait PrimeField: Field + From<u64> {
/// `modulus - 1`.
const S: u32;
- /// Returns the `2^s` root of unity.
+ /// The `2^s` root of unity.
///
- /// It can be calculated by exponentiating `Self::multiplicative_generator` by `t`,
+ /// It can be calculated by exponentiating `Self::MULTIPLICATIVE_GENERATOR` by `t`,
/// where `t = (modulus - 1) >> Self::S`.
- fn root_of_unity() -> Self;
+ const ROOT_OF_UNITY: Self;
+
+ /// Inverse of [`Self::ROOT_OF_UNITY`].
+ const ROOT_OF_UNITY_INV: Self;
+
+ /// Generator of the `t-order` multiplicative subgroup.
+ ///
+ /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`,
+ /// where `s` is [`Self::S`].
+ const DELTA: Self;
+}
+
+/// The subset of prime-order fields such that `(modulus - 1)` is divisible by `N`.
+///
+/// If `N` is prime, there will be `N - 1` valid choices of [`Self::ZETA`]. Similarly to
+/// [`PrimeField::MULTIPLICATIVE_GENERATOR`], the specific choice does not matter, as long
+/// as the choice is consistent across all uses of the field.
+pub trait WithSmallOrderMulGroup<const N: u8>: PrimeField {
+ /// A field element of small multiplicative order $N$.
+ ///
+ /// The presense of this element allows you to perform (certain types of)
+ /// endomorphisms on some elliptic curves.
+ ///
+ /// It can be calculated using [SageMath] as
+ /// `GF(modulus).primitive_element() ^ ((modulus - 1) // N)`.
+ /// Choosing the element of order $N$ that is smallest, when considered
+ /// as an integer, may help to ensure consistency.
+ ///
+ /// [SageMath]: https://www.sagemath.org/
+ const ZETA: Self;
+}
+
+/// Trait for constructing a [`PrimeField`] element from a fixed-length uniform byte
+/// array.
+///
+/// "Uniform" means that the byte array's contents must be indistinguishable from the
+/// [discrete uniform distribution]. Suitable byte arrays can be obtained:
+/// - from a cryptographically-secure randomness source (which makes this constructor
+/// equivalent to [`Field::random`]).
+/// - from a cryptographic hash function output, which enables a "random" field element to
+/// be selected deterministically. This is the primary use case for `FromUniformBytes`.
+///
+/// The length `N` of the byte array is chosen by the trait implementer such that the loss
+/// of uniformity in the mapping from byte arrays to field elements is cryptographically
+/// negligible.
+///
+/// [discrete uniform distribution]: https://en.wikipedia.org/wiki/Discrete_uniform_distribution
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "derive")] {
+/// # // Fake this so we don't actually need a dev-dependency on bls12_381.
+/// # mod bls12_381 {
+/// # use ff::{Field, PrimeField};
+/// #
+/// # #[derive(PrimeField)]
+/// # #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
+/// # #[PrimeFieldGenerator = "7"]
+/// # #[PrimeFieldReprEndianness = "little"]
+/// # pub struct Scalar([u64; 4]);
+/// #
+/// # impl ff::FromUniformBytes<64> for Scalar {
+/// # fn from_uniform_bytes(_bytes: &[u8; 64]) -> Self {
+/// # // Fake impl for doctest
+/// # Scalar::ONE
+/// # }
+/// # }
+/// # }
+/// #
+/// use blake2b_simd::blake2b;
+/// use bls12_381::Scalar;
+/// use ff::FromUniformBytes;
+///
+/// // `bls12_381::Scalar` implements `FromUniformBytes<64>`, and BLAKE2b (by default)
+/// // produces a 64-byte hash.
+/// let hash = blake2b(b"Some message");
+/// let val = Scalar::from_uniform_bytes(hash.as_array());
+/// # }
+/// ```
+///
+/// # Implementing `FromUniformBytes`
+///
+/// [`Self::from_uniform_bytes`] should always be implemented by interpreting the provided
+/// byte array as the little endian unsigned encoding of an integer, and then reducing that
+/// integer modulo the field modulus.
+///
+/// For security, `N` must be chosen so that `N * 8 >= Self::NUM_BITS + 128`. A larger
+/// value of `N` may be chosen for convenience; for example, for a field with a 255-bit
+/// modulus, `N = 64` is convenient as it matches the output length of several common
+/// cryptographic hash functions (such as SHA-512 and BLAKE2b).
+///
+/// ## Trait design
+///
+/// This trait exists because `PrimeField::from_uniform_bytes([u8; N])` cannot currently
+/// exist (trait methods cannot use associated constants in the const positions of their
+/// type signature, and we do not want `PrimeField` to require a generic const parameter).
+/// However, this has the side-effect that `FromUniformBytes` can be implemented multiple
+/// times for different values of `N`. Most implementations of [`PrimeField`] should only
+/// need to implement `FromUniformBytes` trait for one value of `N` (chosen following the
+/// above considerations); if you find yourself needing to implement it multiple times,
+/// please [let us know about your use case](https://github.com/zkcrypto/ff/issues/new) so
+/// we can take it into consideration for future evolutions of the `ff` traits.
+pub trait FromUniformBytes<const N: usize>: PrimeField {
+ /// Returns a field element that is congruent to the provided little endian unsigned
+ /// byte representation of an integer.
+ fn from_uniform_bytes(bytes: &[u8; N]) -> Self;
}
/// This represents the bits of an element of a prime field.