Skip to main content

curve25519_dalek/
field.rs

1// -*- mode: rust; -*-
2//
3// This file is part of curve25519-dalek.
4// Copyright (c) 2016-2021 isis agora lovecruft
5// Copyright (c) 2016-2019 Henry de Valence
6// See LICENSE for licensing information.
7//
8// Authors:
9// - Isis Agora Lovecruft <[email protected]>
10// - Henry de Valence <[email protected]>
11
12//! Field arithmetic modulo \\(p = 2\^{255} - 19\\).
13//!
14//! The `curve25519_dalek::field` module provides a type alias
15//! `curve25519_dalek::field::FieldElement` to a field element type
16//! defined in the `backend` module; either `FieldElement51` or
17//! `FieldElement2625`.
18//!
19//! Field operations defined in terms of machine
20//! operations, such as field multiplication or squaring, are defined in
21//! the backend implementation.
22//!
23//! Field operations defined in terms of other field operations, such as
24//! field inversion or square roots, are defined here.
25
26#![allow(unused_qualifications)]
27
28use cfg_if::cfg_if;
29
30use subtle::Choice;
31use subtle::ConditionallyNegatable;
32use subtle::ConditionallySelectable;
33use subtle::ConstantTimeEq;
34
35use crate::backend;
36use crate::constants;
37
38#[cfg(feature = "digest")]
39use digest::{
40    Digest, FixedOutput, HashMarker,
41    array::{Array, typenum::U64},
42    block_api::BlockSizeUser,
43    typenum::{IsGreater, True},
44};
45
46cfg_if! {
47    if #[cfg(curve25519_dalek_backend = "fiat")] {
48        /// A `FieldElement` represents an element of the field
49        /// \\( \mathbb Z / (2\^{255} - 19)\\).
50        ///
51        /// The `FieldElement` type is an alias for one of the platform-specific
52        /// implementations.
53        ///
54        /// Using formally-verified field arithmetic from fiat-crypto.
55        #[cfg(curve25519_dalek_bits = "32")]
56        pub(crate) type FieldElement = backend::serial::fiat_u32::field::FieldElement2625;
57
58        /// A `FieldElement` represents an element of the field
59        /// \\( \mathbb Z / (2\^{255} - 19)\\).
60        ///
61        /// The `FieldElement` type is an alias for one of the platform-specific
62        /// implementations.
63        ///
64        /// Using formally-verified field arithmetic from fiat-crypto.
65        #[cfg(curve25519_dalek_bits = "64")]
66        pub(crate) type FieldElement = backend::serial::fiat_u64::field::FieldElement51;
67    } else if #[cfg(curve25519_dalek_bits = "64")] {
68        /// A `FieldElement` represents an element of the field
69        /// \\( \mathbb Z / (2\^{255} - 19)\\).
70        ///
71        /// The `FieldElement` type is an alias for one of the platform-specific
72        /// implementations.
73        pub(crate) type FieldElement = backend::serial::u64::field::FieldElement51;
74    } else {
75        /// A `FieldElement` represents an element of the field
76        /// \\( \mathbb Z / (2\^{255} - 19)\\).
77        ///
78        /// The `FieldElement` type is an alias for one of the platform-specific
79        /// implementations.
80        pub(crate) type FieldElement = backend::serial::u32::field::FieldElement2625;
81    }
82}
83
84impl Eq for FieldElement {}
85
86impl PartialEq for FieldElement {
87    fn eq(&self, other: &FieldElement) -> bool {
88        self.ct_eq(other).into()
89    }
90}
91
92impl ConstantTimeEq for FieldElement {
93    /// Test equality between two `FieldElement`s.  Since the
94    /// internal representation is not canonical, the field elements
95    /// are normalized to wire format before comparison.
96    fn ct_eq(&self, other: &FieldElement) -> Choice {
97        self.to_bytes().ct_eq(&other.to_bytes())
98    }
99}
100
101impl Default for FieldElement {
102    fn default() -> Self {
103        FieldElement::ZERO
104    }
105}
106
107impl FieldElement {
108    /// Load a `FieldElement` from 64 bytes, by reducing modulo q.
109    #[cfg(feature = "digest")]
110    pub(crate) fn from_bytes_wide(bytes: &[u8; 64]) -> Self {
111        let mut fl = [0u8; 32];
112        let mut gl = [0u8; 32];
113        fl.copy_from_slice(&bytes[..32]);
114        gl.copy_from_slice(&bytes[32..]);
115        // Mask off the top bits of both halves, since from_bytes masks them off anyway. We'll add
116        // them back in later.
117        let fl_top_bit = (fl[31] >> 7) as u16;
118        let gl_top_bit = (gl[31] >> 7) as u16;
119        fl[31] &= 0x7f;
120        gl[31] &= 0x7f;
121
122        // Interpret both sides as field elements
123        let mut fe_f = Self::from_bytes(&fl);
124        let fe_g = Self::from_bytes(&gl);
125
126        // The full field elem is now fe_f + 2²⁵⁵ fl_top_bit + 2²⁵⁶ fe_g + 2⁵¹¹ gl_top_bit
127
128        // Add the masked off bits back to fe_f. fl_top_bit, if set, is 2^255 ≡ 19 (mod q).
129        // gl_top_bit, if set, is 2^511 ≡ 722 (mod q)
130        let top_bits_sum = {
131            // This only need to be a u16 because the max value is 741
132            let addend: u16 = fl_top_bit * 19 + gl_top_bit * 722;
133            let mut addend_bytes = [0u8; 32];
134            addend_bytes[..2].copy_from_slice(&addend.to_le_bytes());
135            Self::from_bytes(&addend_bytes)
136        };
137        fe_f += &top_bits_sum;
138
139        // Now add the high half into fe_f. The RHS is multiplied by 2^256 ≡ 38 (mod q)
140        const THIRTY_EIGHT: FieldElement = FieldElement::from_bytes(&[
141            38, 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,
142            0, 0, 0,
143        ]);
144        fe_f += &(&THIRTY_EIGHT * &fe_g);
145
146        fe_f
147    }
148
149    /// Determine if this `FieldElement` is negative, in the sense
150    /// used in the ed25519 paper: `x` is negative if the low bit is
151    /// set.
152    ///
153    /// # Return
154    ///
155    /// If negative, return `Choice(1)`.  Otherwise, return `Choice(0)`.
156    pub(crate) fn is_negative(&self) -> Choice {
157        let bytes = self.to_bytes();
158        (bytes[0] & 1).into()
159    }
160
161    /// Determine if this `FieldElement` is zero.
162    ///
163    /// # Return
164    ///
165    /// If zero, return `Choice(1)`.  Otherwise, return `Choice(0)`.
166    pub(crate) fn is_zero(&self) -> Choice {
167        let zero = [0u8; 32];
168        let bytes = self.to_bytes();
169
170        bytes.ct_eq(&zero)
171    }
172
173    /// Compute (self^(2^250-1), self^11), used as a helper function
174    /// within invert() and pow22523().
175    #[rustfmt::skip] // keep alignment of explanatory comments
176    fn pow22501(&self) -> (FieldElement, FieldElement) {
177        // Instead of managing which temporary variables are used
178        // for what, we define as many as we need and leave stack
179        // allocation to the compiler
180        //
181        // Each temporary variable t_i is of the form (self)^e_i.
182        // Squaring t_i corresponds to multiplying e_i by 2,
183        // so the pow2k function shifts e_i left by k places.
184        // Multiplying t_i and t_j corresponds to adding e_i + e_j.
185        //
186        // Temporary t_i                      Nonzero bits of e_i
187        //
188        let t0  = self.square();           // 1         e_0 = 2^1
189        let t1  = t0.square().square();    // 3         e_1 = 2^3
190        let t2  = self * &t1;              // 3,0       e_2 = 2^3 + 2^0
191        let t3  = &t0 * &t2;               // 3,1,0
192        let t4  = t3.square();             // 4,2,1
193        let t5  = &t2 * &t4;               // 4,3,2,1,0
194        let t6  = t5.pow2k(5);             // 9,8,7,6,5
195        let t7  = &t6 * &t5;               // 9,8,7,6,5,4,3,2,1,0
196        let t8  = t7.pow2k(10);            // 19..10
197        let t9  = &t8 * &t7;               // 19..0
198        let t10 = t9.pow2k(20);            // 39..20
199        let t11 = &t10 * &t9;              // 39..0
200        let t12 = t11.pow2k(10);           // 49..10
201        let t13 = &t12 * &t7;              // 49..0
202        let t14 = t13.pow2k(50);           // 99..50
203        let t15 = &t14 * &t13;             // 99..0
204        let t16 = t15.pow2k(100);          // 199..100
205        let t17 = &t16 * &t15;             // 199..0
206        let t18 = t17.pow2k(50);           // 249..50
207        let t19 = &t18 * &t13;             // 249..0
208
209        (t19, t3)
210    }
211
212    /// Given a slice of pub(crate)lic `FieldElements`, replace each with its inverse.
213    ///
214    /// When an input `FieldElement` is zero, its value is unchanged.
215    pub(crate) fn invert_batch<const N: usize>(inputs: &mut [FieldElement; N]) {
216        let mut scratch = [FieldElement::ONE; N];
217
218        Self::internal_invert_batch(inputs, &mut scratch);
219    }
220
221    /// Given a slice of pub(crate)lic `FieldElements`, replace each with its inverse.
222    ///
223    /// When an input `FieldElement` is zero, its value is unchanged.
224    #[cfg(feature = "alloc")]
225    pub(crate) fn invert_batch_alloc(inputs: &mut [FieldElement]) {
226        let n = inputs.len();
227        let mut scratch = vec![FieldElement::ONE; n];
228
229        Self::internal_invert_batch(inputs, &mut scratch);
230    }
231
232    /// Given a slice of pub(crate)lic `FieldElements`, replace each with its inverse. `scratch` can
233    /// contain anything, so long as its length is the same as `inputs`.
234    ///
235    /// When an input `FieldElement` is zero, its value is unchanged.
236    ///
237    /// # Panics
238    /// Panics when `scratch.len() != inputs.len()`
239    fn internal_invert_batch(inputs: &mut [FieldElement], scratch: &mut [FieldElement]) {
240        // Montgomery’s Trick and Fast Implementation of Masked AES
241        // Genelle, Prouff and Quisquater
242        // Section 3.2
243
244        debug_assert_eq!(inputs.len(), scratch.len());
245
246        // Keep an accumulator of all of the previous products
247        let mut acc = FieldElement::ONE;
248
249        // Pass through the input vector, recording the previous
250        // products in the scratch space
251        for (input, scratch) in inputs.iter().zip(scratch.iter_mut()) {
252            *scratch = acc;
253            // acc <- acc * input, but skipping zeros (constant-time)
254            acc.conditional_assign(&(&acc * input), !input.is_zero());
255        }
256
257        // acc is nonzero because we skipped zeros in inputs
258        assert!(bool::from(!acc.is_zero()));
259
260        // Compute the inverse of all products
261        acc = acc.invert();
262
263        // Pass through the vector backwards to compute the inverses
264        // in place
265        for (input, scratch) in inputs.iter_mut().rev().zip(scratch.iter_mut().rev()) {
266            let tmp = &acc * input;
267            // input <- acc * scratch, then acc <- tmp
268            // Again, we skip zeros in a constant-time way
269            let nz = !input.is_zero();
270            input.conditional_assign(&(&acc * scratch), nz);
271            acc.conditional_assign(&tmp, nz);
272        }
273    }
274
275    /// Given a nonzero field element, compute its inverse.
276    ///
277    /// The inverse is computed as self^(p-2), since
278    /// x^(p-2)x = x^(p-1) = 1 (mod p).
279    ///
280    /// This function returns zero on input zero.
281    #[rustfmt::skip] // keep alignment of explanatory comments
282    #[allow(clippy::let_and_return)]
283    pub(crate) fn invert(&self) -> FieldElement {
284        // The bits of p-2 = 2^255 -19 -2 are 11010111111...11.
285        //
286        //                                 nonzero bits of exponent
287        let (t19, t3) = self.pow22501();   // t19: 249..0 ; t3: 3,1,0
288        let t20 = t19.pow2k(5);            // 254..5
289        let t21 = &t20 * &t3;              // 254..5,3,1,0
290
291        t21
292    }
293
294    /// Raise this field element to the power (p-5)/8 = 2^252 -3.
295    #[rustfmt::skip] // keep alignment of explanatory comments
296    #[allow(clippy::let_and_return)]
297    pub(crate) fn pow_p58(&self) -> FieldElement {
298        // The bits of (p-5)/8 are 101111.....11.
299        //
300        //                                 nonzero bits of exponent
301        let (t19, _) = self.pow22501();    // 249..0
302        let t20 = t19.pow2k(2);            // 251..2
303        let t21 = self * &t20;             // 251..2,0
304
305        t21
306    }
307
308    /// Given `FieldElements` `u` and `v`, compute either `sqrt(u/v)`
309    /// or `sqrt(i*u/v)` in constant time.
310    ///
311    /// This function always returns the nonnegative square root.
312    ///
313    /// # Return
314    ///
315    /// - `(Choice(1), +sqrt(u/v))  ` if `v` is nonzero and `u/v` is square;
316    /// - `(Choice(1), zero)        ` if `u` is zero;
317    /// - `(Choice(0), zero)        ` if `v` is zero and `u` is nonzero;
318    /// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square).
319    ///
320    pub(crate) fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) {
321        // Using the same trick as in ed25519 decoding, we merge the
322        // inversion, the square root, and the square test as follows.
323        //
324        // To compute sqrt(α), we can compute β = α^((p+3)/8).
325        // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary
326        // gives sqrt(α).
327        //
328        // To compute 1/sqrt(α), we observe that
329        //    1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8)
330        //                            = α^3 * (α^7)^((p-5)/8).
331        //
332        // We can therefore compute sqrt(u/v) = sqrt(u)/sqrt(v)
333        // by first computing
334        //    r = u^((p+3)/8) v^(p-1-(p+3)/8)
335        //      = u u^((p-5)/8) v^3 (v^7)^((p-5)/8)
336        //      = (uv^3) (uv^7)^((p-5)/8).
337        //
338        // If v is nonzero and u/v is square, then r^2 = ±u/v,
339        //                                     so vr^2 = ±u.
340        // If vr^2 =  u, then sqrt(u/v) = r.
341        // If vr^2 = -u, then sqrt(u/v) = r*sqrt(-1).
342        //
343        // If v is zero, r is also zero.
344
345        let v3 = &v.square() * v;
346        let v7 = &v3.square() * v;
347        let mut r = &(u * &v3) * &(u * &v7).pow_p58();
348        let check = v * &r.square();
349
350        let i = &constants::SQRT_M1;
351
352        let correct_sign_sqrt = check.ct_eq(u);
353        let flipped_sign_sqrt = check.ct_eq(&(-u));
354        let flipped_sign_sqrt_i = check.ct_eq(&(&(-u) * i));
355
356        let r_prime = &constants::SQRT_M1 * &r;
357        r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i);
358
359        // Choose the nonnegative square root.
360        let r_is_negative = r.is_negative();
361        r.conditional_negate(r_is_negative);
362
363        let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt;
364
365        (was_nonzero_square, r)
366    }
367
368    /// Attempt to compute `sqrt(1/self)` in constant time.
369    ///
370    /// Convenience wrapper around `sqrt_ratio_i`.
371    ///
372    /// This function always returns the nonnegative square root.
373    ///
374    /// # Return
375    ///
376    /// - `(Choice(1), +sqrt(1/self))  ` if `self` is a nonzero square;
377    /// - `(Choice(0), zero)           ` if `self` is zero;
378    /// - `(Choice(0), +sqrt(i/self))  ` if `self` is a nonzero nonsquare;
379    ///
380    pub(crate) fn invsqrt(&self) -> (Choice, FieldElement) {
381        FieldElement::sqrt_ratio_i(&FieldElement::ONE, self)
382    }
383
384    #[cfg(feature = "digest")]
385    /// Hashes the given message and domain separator to produce `COUNT` [`FieldElement`]s, per RFC
386    /// 9380. The hash's input is the concatenation of the elements of `msg`. Likewise for the
387    /// domain separator with `domain_sep`. At least one element of `domain_sep`, MUST be nonempty,
388    /// its concatenation MUST NOT exceed 255 bytes, and `COUNT` MUST be 1 or 2.
389    ///
390    /// The specification names SHA-512 as an example of a secure hash to use with this function,
391    /// but you may use any 512-bit hash within reason (see the
392    /// [`spec`](https://www.rfc-editor.org/rfc/rfc9380.html#section-5.2) for details).
393    ///
394    /// # Panics
395    /// Panics if `domain_sep.collect().len() == 0` or `> 255`. Also panics if `COUNT > 2` or
396    /// `COUNT == 0`.
397    pub fn hash_to_field<D, const COUNT: usize>(
398        msg: &[&[u8]],
399        domain_sep: &[&[u8]],
400    ) -> [Self; COUNT]
401    where
402        D: BlockSizeUser + Default + FixedOutput<OutputSize = U64> + HashMarker,
403        D::BlockSize: IsGreater<D::OutputSize, Output = True>,
404    {
405        // We only use `hash_to_field` for Elligator2, which uses 0 < COUNT <= 2
406        assert!(COUNT == 1 || COUNT == 2);
407
408        // §5.2, we generate count * m * L = COUNT * 1 * (256 + 128)/8 bytes
409        let len_in_bytes = COUNT * 48;
410        // Buffer should hold however many digests we need to produce len_in_bytes bytes.
411        // len_in_bytes is at most 2*48=96, and the digest is 64B. So that's 2 digests, or 128B
412        let mut buf = [0u8; 128];
413        // We can call this without worrying about panics: len_in_bytes is at most 96, and buf is
414        // bigger than it. Further, if `domain_sep` is too large, that's also a panic condition of
415        // this function so it's fine
416        let uniform_bytes = expand_msg_xmd::<D>(msg, domain_sep, &mut buf, len_in_bytes);
417
418        let mut result = [FieldElement::ONE; COUNT];
419        for i in 0..COUNT {
420            let mut bytes_wide = [0u8; 64];
421            bytes_wide[..48].copy_from_slice(&uniform_bytes[48 * i..48 * (i + 1)]);
422            bytes_wide[..48].reverse();
423
424            result[i] = FieldElement::from_bytes_wide(&bytes_wide);
425        }
426
427        result
428    }
429}
430
431/// Hashes the concatenation of the elements of `msg` with domain separator equal to the
432/// concatenation of `domain_sep`. The output is an `outlen`-length slice into `buf`. Follows
433/// https://www.rfc-editor.org/rfc/rfc9380.html#section-5.3.1
434///
435/// # Panics
436/// Panics if the domain separator is empty, if the total length of the domain separator is more
437/// than 255 bytes, if `outlen` is more than `255 * D::output_size()`, if `outlen is more than
438/// 65535, or if `dst.len() < outlen`.
439#[cfg(feature = "digest")]
440fn expand_msg_xmd<'a, D>(
441    msg: &[&[u8]],
442    domain_sep: &[&[u8]],
443    buf: &'a mut [u8],
444    outlen: usize,
445) -> &'a [u8]
446where
447    D: BlockSizeUser + Default + FixedOutput + HashMarker,
448{
449    use core::iter::once;
450
451    // The notation we use in this function is the same as in the spec
452    let len_in_bytes = u16::try_from(outlen).expect("outlen must not exceed 65535");
453
454    assert!(buf.len() >= outlen);
455    let ell = u8::try_from((len_in_bytes as usize).div_ceil(D::output_size()))
456        .expect("output length cannot exceed 255 times digest size");
457    let domain_sep_len = u8::try_from(domain_sep.iter().map(|c| c.len()).sum::<usize>())
458        .expect("unexpected overflow from domain separator's size.");
459    assert_ne!(
460        domain_sep_len, 0,
461        "domain separator MUST have nonzero length."
462    );
463
464    let domain_sep_len_slice = &[domain_sep_len][..];
465    let dst_prime = domain_sep.iter().copied().chain(once(domain_sep_len_slice));
466    let z_pad = Array::<u8, D::BlockSize>::default();
467    let l_i_b_str = len_in_bytes.to_be_bytes();
468
469    // Collect the components of msg_prime
470    let msg_prime = once(z_pad.as_slice())
471        .chain(msg.iter().copied())
472        .chain(once(l_i_b_str.as_slice()))
473        .chain(once(&[0u8][..]))
474        .chain(dst_prime.clone());
475    // Hash all of msg_prime
476    let b_0 = msg_prime
477        .fold(D::new(), |h, slice| h.chain_update(slice))
478        .finalize();
479
480    // Collect the input components for the b_1 hash
481    let b_1_input = once(b_0.as_slice())
482        .chain(once(&[1u8][..]))
483        .chain(dst_prime.clone());
484    let b_1 = b_1_input
485        .fold(D::new(), |h, slice| h.chain_update(slice))
486        .finalize();
487    // Write b_1 to the output buffer
488    buf[..D::output_size()].copy_from_slice(&b_1);
489
490    for i in 2..=ell {
491        // Get the last digest we produced
492        let i_ = i as usize;
493        let last_b = &buf[(i_ - 2) * D::output_size()..(i_ - 1) * D::output_size()];
494        // XOR it with b_0
495        let mut xor_bs = b_0.clone();
496        xor_bs
497            .as_mut_slice()
498            .iter_mut()
499            .zip(last_b)
500            .for_each(|(l, r)| *l ^= *r);
501
502        // Hash (b_0 ^ b_{i-1}) || i || dst_prime
503        let i_slice = &[i][..];
504        let b_i_input = once(xor_bs.as_slice())
505            .chain(once(i_slice))
506            .chain(dst_prime.clone());
507        let b_i = b_i_input
508            .fold(D::new(), |h, slice| h.chain_update(slice))
509            .finalize();
510
511        // Write b_i to the output buffer
512        buf[(i_ - 1) * D::output_size()..i_ * D::output_size()].copy_from_slice(&b_i);
513    }
514
515    &buf[..outlen]
516}
517
518#[cfg(test)]
519mod test {
520    use crate::field::*;
521
522    /// Random element a of GF(2^255-19), from Sage
523    /// a = 1070314506888354081329385823235218444233221\
524    ///     2228051251926706380353716438957572
525    static A_BYTES: [u8; 32] = [
526        0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68, 0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7,
527        0x03, 0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4, 0xa4, 0x51, 0x47, 0x36, 0xf3, 0xc3,
528        0xa9, 0x17,
529    ];
530
531    /// Byte representation of a**2
532    static ASQ_BYTES: [u8; 32] = [
533        0x75, 0x97, 0x24, 0x9e, 0xe6, 0x06, 0xfe, 0xab, 0x24, 0x04, 0x56, 0x68, 0x07, 0x91, 0x2d,
534        0x5d, 0x0b, 0x0f, 0x3f, 0x1c, 0xb2, 0x6e, 0xf2, 0xe2, 0x63, 0x9c, 0x12, 0xba, 0x73, 0x0b,
535        0xe3, 0x62,
536    ];
537
538    /// Byte representation of 1/a
539    static AINV_BYTES: [u8; 32] = [
540        0x96, 0x1b, 0xcd, 0x8d, 0x4d, 0x5e, 0xa2, 0x3a, 0xe9, 0x36, 0x37, 0x93, 0xdb, 0x7b, 0x4d,
541        0x70, 0xb8, 0x0d, 0xc0, 0x55, 0xd0, 0x4c, 0x1d, 0x7b, 0x90, 0x71, 0xd8, 0xe9, 0xb6, 0x18,
542        0xe6, 0x30,
543    ];
544
545    /// Byte representation of a^((p-5)/8)
546    static AP58_BYTES: [u8; 32] = [
547        0x6a, 0x4f, 0x24, 0x89, 0x1f, 0x57, 0x60, 0x36, 0xd0, 0xbe, 0x12, 0x3c, 0x8f, 0xf5, 0xb1,
548        0x59, 0xe0, 0xf0, 0xb8, 0x1b, 0x20, 0xd2, 0xb5, 0x1f, 0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61,
549        0x21, 0x55,
550    ];
551
552    #[test]
553    fn a_mul_a_vs_a_squared_constant() {
554        let a = FieldElement::from_bytes(&A_BYTES);
555        let asq = FieldElement::from_bytes(&ASQ_BYTES);
556        assert_eq!(asq, &a * &a);
557    }
558
559    #[test]
560    fn a_square_vs_a_squared_constant() {
561        let a = FieldElement::from_bytes(&A_BYTES);
562        let asq = FieldElement::from_bytes(&ASQ_BYTES);
563        assert_eq!(asq, a.square());
564    }
565
566    #[test]
567    fn a_square2_vs_a_squared_constant() {
568        let a = FieldElement::from_bytes(&A_BYTES);
569        let asq = FieldElement::from_bytes(&ASQ_BYTES);
570        assert_eq!(a.square2(), &asq + &asq);
571    }
572
573    #[test]
574    fn a_invert_vs_inverse_of_a_constant() {
575        let a = FieldElement::from_bytes(&A_BYTES);
576        let ainv = FieldElement::from_bytes(&AINV_BYTES);
577        let should_be_inverse = a.invert();
578        assert_eq!(ainv, should_be_inverse);
579        assert_eq!(FieldElement::ONE, &a * &should_be_inverse);
580    }
581
582    #[test]
583    #[cfg(feature = "alloc")]
584    fn invert_batch_a_matches_nonbatched() {
585        let a = FieldElement::from_bytes(&A_BYTES);
586        let ap58 = FieldElement::from_bytes(&AP58_BYTES);
587        let asq = FieldElement::from_bytes(&ASQ_BYTES);
588        let ainv = FieldElement::from_bytes(&AINV_BYTES);
589        let a0 = &a - &a;
590        let a2 = &a + &a;
591        let a_list = vec![a, ap58, asq, ainv, a0, a2];
592        let mut ainv_list = a_list.clone();
593        FieldElement::invert_batch_alloc(&mut ainv_list[..]);
594        for i in 0..6 {
595            assert_eq!(a_list[i].invert(), ainv_list[i]);
596        }
597    }
598
599    #[test]
600    fn sqrt_ratio_behavior() {
601        let zero = FieldElement::ZERO;
602        let one = FieldElement::ONE;
603        let i = constants::SQRT_M1;
604        let two = &one + &one; // 2 is nonsquare mod p.
605        let four = &two + &two; // 4 is square mod p.
606
607        // 0/0 should return (1, 0) since u is 0
608        let (choice, sqrt) = FieldElement::sqrt_ratio_i(&zero, &zero);
609        assert!(bool::from(choice));
610        assert_eq!(sqrt, zero);
611        assert!(bool::from(!sqrt.is_negative()));
612
613        // 1/0 should return (0, 0) since v is 0, u is nonzero
614        let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &zero);
615        assert!(bool::from(!choice));
616        assert_eq!(sqrt, zero);
617        assert!(bool::from(!sqrt.is_negative()));
618
619        // 2/1 is nonsquare, so we expect (0, sqrt(i*2))
620        let (choice, sqrt) = FieldElement::sqrt_ratio_i(&two, &one);
621        assert!(bool::from(!choice));
622        assert_eq!(sqrt.square(), &two * &i);
623        assert!(bool::from(!sqrt.is_negative()));
624
625        // 4/1 is square, so we expect (1, sqrt(4))
626        let (choice, sqrt) = FieldElement::sqrt_ratio_i(&four, &one);
627        assert!(bool::from(choice));
628        assert_eq!(sqrt.square(), four);
629        assert!(bool::from(!sqrt.is_negative()));
630
631        // 1/4 is square, so we expect (1, 1/sqrt(4))
632        let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &four);
633        assert!(bool::from(choice));
634        assert_eq!(&sqrt.square() * &four, one);
635        assert!(bool::from(!sqrt.is_negative()));
636    }
637
638    #[test]
639    fn a_p58_vs_ap58_constant() {
640        let a = FieldElement::from_bytes(&A_BYTES);
641        let ap58 = FieldElement::from_bytes(&AP58_BYTES);
642        assert_eq!(ap58, a.pow_p58());
643    }
644
645    #[test]
646    fn equality() {
647        let a = FieldElement::from_bytes(&A_BYTES);
648        let ainv = FieldElement::from_bytes(&AINV_BYTES);
649        assert!(a == a);
650        assert!(a != ainv);
651    }
652
653    /// Notice that the last element has the high bit set, which
654    /// should be ignored
655    static B_BYTES: [u8; 32] = [
656        113, 191, 169, 143, 91, 234, 121, 15, 241, 131, 217, 36, 230, 101, 92, 234, 8, 208, 170,
657        251, 97, 127, 70, 210, 58, 23, 166, 87, 240, 169, 184, 178,
658    ];
659
660    #[test]
661    fn from_bytes_highbit_is_ignored() {
662        let mut cleared_bytes = B_BYTES;
663        cleared_bytes[31] &= 127u8;
664        let with_highbit_set = FieldElement::from_bytes(&B_BYTES);
665        let without_highbit_set = FieldElement::from_bytes(&cleared_bytes);
666        assert_eq!(without_highbit_set, with_highbit_set);
667    }
668
669    #[test]
670    fn conditional_negate() {
671        let one = FieldElement::ONE;
672        let minus_one = FieldElement::MINUS_ONE;
673        let mut x = one;
674        x.conditional_negate(Choice::from(1));
675        assert_eq!(x, minus_one);
676        x.conditional_negate(Choice::from(0));
677        assert_eq!(x, minus_one);
678        x.conditional_negate(Choice::from(1));
679        assert_eq!(x, one);
680    }
681
682    #[test]
683    fn encoding_is_canonical() {
684        // Encode 1 wrongly as 1 + (2^255 - 19) = 2^255 - 18
685        let one_encoded_wrongly_bytes: [u8; 32] = [
686            0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
687            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
688            0xff, 0xff, 0xff, 0x7f,
689        ];
690        // Decode to a field element
691        let one = FieldElement::from_bytes(&one_encoded_wrongly_bytes);
692        // .. then check that the encoding is correct
693        let one_bytes = one.to_bytes();
694        assert_eq!(one_bytes[0], 1);
695        for byte in &one_bytes[1..] {
696            assert_eq!(*byte, 0);
697        }
698    }
699
700    #[test]
701    #[cfg(feature = "alloc")]
702    fn invert_batch_empty() {
703        FieldElement::invert_batch_alloc(&mut []);
704    }
705
706    // The following two consts were generated with the following sage script:
707    //
708    // import random
709    //
710    // F = GF(2**255 - 19)
711    // # Use a seed to make sure we produce the same test vectors every time
712    // random.seed("Ozamataz Buckshank")
713    //
714    // # Generates test vectors, each of the form (input_bytes, reduced_field_elem_bytes),
715    // # where input_bytes is length input_bytes_len
716    // def gen_example(input_bytes_len):
717    //     # Generate random bytes
718    //     input_bytes = [random.randint(0, 255) for _ in range(input_bytes_len)]
719    //
720    //     # Now convert to a field element and get the reduced byte representation
721    //     elem = F(int.from_bytes(input_bytes, byteorder='little'))
722    //     reduced_bytes = list(int(elem).to_bytes(32, byteorder='little'))
723    //
724    //     # Format input and output as hex strings
725    //     input_bytes_hex = ''.join(f'{byte:02x}' for byte in input_bytes)
726    //     reduced_bytes_hex = ''.join(f'{byte:02x}' for byte in reduced_bytes)
727    //     return f"(\"{input_bytes_hex}\", \"{reduced_bytes_hex}\")"
728    //
729    // print("SET 1: Input bytes are length 64")
730    // for _ in range(5):
731    //     print(gen_example(64))
732    //
733    // print("SET 2: Input bytes are length 48")
734    // for _ in range(5):
735    //     print(gen_example(48))
736
737    /// Test vectors for FieldElement::from_bytes_wide. Elements are of the form (len-64 bytestring,
738    /// reduced field element)
739    #[cfg(feature = "digest")]
740    const FROM_BYTES_WIDE_KAT_BIG: &[(&str, &str)] = &[
741        (
742            "77b663085cac0e916f40dbeea5116f201816406e68ccf01b32a97162ae1d5bf95d0d01c2c72fbeeb27a63\
743            5b85b715d5ce6f74118a60a7aec53c798ad648a482f",
744            "62b38bd402c4498f5cead14643e54dd649e20a0810610e36a73f1f27a0a81f7e",
745        ),
746        (
747            "d437c75ec79886650243a79c62933bb307eb12ff16d05db4a6a8a877f4a91abb6eeb64d2e20519c021799\
748            3a1dc5639283a06639985a2c892208171503335afb5",
749            "3d2ec29972783de9043e8b982278beaba9d7c5c3ebef257e7cd38168928f1c33",
750        ),
751        (
752            "6daa9e1abe6c604fb6e841c04bf90a6ef88aef6b1eab17dd44f7207ef472cd2d54bac849f703e64f36e56\
753            77e7e86b82be7d26aa220daf1f208bb36dcc1a12338",
754            "28546a0e7303852bc6eead8312f06eeb48d9ca87f60bfeec98ba402ebb751703",
755        ),
756        (
757            "c3920e326dbf806a50105be78263c1dc9390fb4741587b250cd758c2bfa3ed70faedbbc5f9b1d024e00fe\
758            7d7daf796866853f42e72d638e6533c5eb5b7caf3c6",
759            "40eaf38b802a7be1956ba7f3fe2d2ad717f23f40342deb5180cb55ae04bb1d79",
760        ),
761        (
762            "23f143c72ead6c0f336b4e746a06921f0eb180002e8ce916d196de16216788617c6aeb90a074a85196f03\
763            81375011248927c1215e9ec65b382a6ec556fb3f504",
764            "b1bf354a04fd6d2e8321c24ecb3d3ed2c42e3f21c7b60ab8374effd7a709011e",
765        ),
766    ];
767
768    /// Test vectors for FieldElement::from_bytes_wide. Elements are of the form (len-48 bytestring,
769    /// reduced field element)
770    #[cfg(feature = "digest")]
771    const FROM_BYTES_WIDE_KAT_MEDIUM: &[(&str, &str)] = &[
772        (
773            "82e9cbe4928e3d0bbf1f91824a91acfb30d929f7a2fa5cbcc967c63ea0f3357c29c19f1bc9dcad69d85c1\
774            c6265970685",
775            "989582fe6c540cbbdee7c612570aa7ba44d929f7a2fa5cbcc967c63ea0f3357c",
776        ),
777        (
778            "5480494df4fb3a3b19da17e1c8b9192ccb09ec76720321977079300c42c17b9e95b01eb37ffe7048fcd1c\
779            9e6094da6c4",
780            "85b6d7e3e8c200fc8b050d234129c95ce809ec76720321977079300c42c17b1e",
781        ),
782        (
783            "93ec8a480dde098f74bcd341ef4f248f6440cc6e631d7000784f66975a4fd628438bb1350ba4c1421fec3\
784            670decced06",
785            "8598e540b737c87718c9fae9f3b870966540cc6e631d7000784f66975a4fd628",
786        ),
787        (
788            "fd0154ff9a5c4c9ee4e8183c23db97018e0e6201a812f6d4faedda50652d51f65c110b9a1a100a3fc3ff1\
789            c4ea3cf22e4",
790            "b895f8dc8dc0caf9dfdf66d460adc2deaf0e6201a812f6d4faedda50652d5176",
791        ),
792        (
793            "0e829dc955e0a1e0dbda9849cb2022b295275782348bd6308b3d0c5836f3ca0130911a17fd54054c3a0f8\
794            b2486f8ce85",
795            "2e0f8f37e77d6c29831d3db6b404db8ea9275782348bd6308b3d0c5836f3ca01",
796        ),
797    ];
798
799    #[cfg(feature = "digest")]
800    #[test]
801    fn from_bytes_wide() {
802        // Do the 64-byte input ones first
803        for (input_bytes, expected_reduced) in FROM_BYTES_WIDE_KAT_BIG {
804            let reduce_fe = FieldElement::from_bytes_wide(
805                &hex::decode(input_bytes)
806                    .unwrap()
807                    .as_slice()
808                    .try_into()
809                    .unwrap(),
810            );
811            assert_eq!(
812                &reduce_fe.to_bytes(),
813                hex::decode(expected_reduced).unwrap().as_slice()
814            );
815        }
816
817        // Now do the 48-byte inputs
818        for (input_bytes, expected_reduced) in FROM_BYTES_WIDE_KAT_MEDIUM {
819            let mut padded_input_bytes = [0u8; 64];
820            padded_input_bytes[..48].copy_from_slice(&hex::decode(input_bytes).unwrap());
821            let reduce_fe = FieldElement::from_bytes_wide(&padded_input_bytes);
822            assert_eq!(
823                &reduce_fe.to_bytes(),
824                hex::decode(expected_reduced).unwrap().as_slice()
825            );
826        }
827    }
828
829    #[cfg(feature = "digest")]
830    fn fe_from_test_vector(expected_hex: &str) -> FieldElement {
831        let mut expected_hash = hex::decode(expected_hex).unwrap();
832        expected_hash.reverse();
833        FieldElement::from_bytes(&expected_hash.try_into().unwrap())
834    }
835
836    /// Hash to field test vectors from
837    /// https://www.rfc-editor.org/rfc/rfc9380.html#appendix-J.5.2
838    /// These are of the form (input_msg, output_field_elem)
839    #[cfg(feature = "digest")]
840    const RFC_HASH_TO_FIELD_KAT: &[(&[u8], &str)] = &[
841        (
842            b"",
843            "7f3e7fb9428103ad7f52db32f9df32505d7b427d894c5093f7a0f0374a30641d"
844        ),
845        (
846            b"abc",
847            "09cfa30ad79bd59456594a0f5d3a76f6b71c6787b04de98be5cd201a556e253b"
848        ),
849        (
850            b"abcdef0123456789",
851            "475ccff99225ef90d78cc9338e9f6a6bb7b17607c0c4428937de75d33edba941",
852        ),
853        (
854            b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
855            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
856            "049a1c8bd51bcb2aec339f387d1ff51428b88d0763a91bcdf6929814ac95d03d"
857        ),
858        (
859            b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
860            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
861            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
862            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
863            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
864            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
865            "3cb0178a8137cefa5b79a3a57c858d7eeeaa787b2781be4a362a2f0750d24fa0"
866        )
867    ];
868
869    #[test]
870    #[cfg(feature = "digest")]
871    fn hash_to_field() {
872        use sha2::Sha512;
873        let dst = "QUUX-V01-CS02-with-edwards25519_XMD:SHA-512_ELL2_NU_";
874
875        for (msg, expected_hash_hex) in RFC_HASH_TO_FIELD_KAT {
876            let fe = FieldElement::hash_to_field::<Sha512, 1>(&[msg], &[dst.as_bytes()])[0];
877            let expected_fe = fe_from_test_vector(expected_hash_hex);
878
879            assert_eq!(fe, expected_fe);
880        }
881    }
882
883    /// Hash to field test vectors from
884    /// https://www.rfc-editor.org/rfc/rfc9380.html#appendix-J.5.1
885    /// These are of the form (input_msg, output_field_elem, output_field_elem)
886    #[cfg(feature = "digest")]
887    const RFC_HASH_TO_FIELD_KAT_2: &[(&[u8], &str, &str)] = &[
888        (
889            b"",
890            "03fef4813c8cb5f98c6eef88fae174e6e7d5380de2b007799ac7ee712d203f3a",
891            "780bdddd137290c8f589dc687795aafae35f6b674668d92bf92ae793e6a60c75"
892        ),
893        (
894            b"abc",
895            "5081955c4141e4e7d02ec0e36becffaa1934df4d7a270f70679c78f9bd57c227",
896            "005bdc17a9b378b6272573a31b04361f21c371b256252ae5463119aa0b925b76"
897        ),
898        (
899            b"abcdef0123456789",
900            "285ebaa3be701b79871bcb6e225ecc9b0b32dff2d60424b4c50642636a78d5b3",
901            "2e253e6a0ef658fedb8e4bd6a62d1544fd6547922acb3598ec6b369760b81b31"
902        ),
903        (
904            b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
905            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
906            "4fedd25431c41f2a606952e2945ef5e3ac905a42cf64b8b4d4a83c533bf321af",
907            "02f20716a5801b843987097a8276b6d869295b2e11253751ca72c109d37485a9"
908        ),
909        (
910            b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
911            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
912            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
913            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
914            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
915            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
916            "6e34e04a5106e9bd59f64aba49601bf09d23b27f7b594e56d5de06df4a4ea33b",
917            "1c1c2cb59fc053f44b86c5d5eb8c1954b64976d0302d3729ff66e84068f5fd96"
918        )
919    ];
920
921    #[test]
922    #[cfg(feature = "digest")]
923    fn hash_to_field_2() {
924        use sha2::Sha512;
925        let dst = "QUUX-V01-CS02-with-edwards25519_XMD:SHA-512_ELL2_RO_";
926
927        for (msg, expected_hash_hex_1, expected_hash_hex_2) in
928            crate::field::test::RFC_HASH_TO_FIELD_KAT_2
929        {
930            let fe = FieldElement::hash_to_field::<Sha512, 2>(&[msg], &[dst.as_bytes()]);
931
932            let expected_fe_1 = fe_from_test_vector(expected_hash_hex_1);
933            assert_eq!(fe[0], expected_fe_1);
934
935            let expected_fe_2 = fe_from_test_vector(expected_hash_hex_2);
936            assert_eq!(fe[1], expected_fe_2);
937        }
938    }
939}