curve25519_dalek/
edwards.rs

1// -*- mode: rust; -*-
2//
3// This file is part of curve25519-dalek.
4// Copyright (c) 2016-2021 isis lovecruft
5// Copyright (c) 2016-2020 Henry de Valence
6// See LICENSE for licensing information.
7//
8// Authors:
9// - isis agora lovecruft <isis@patternsinthevoid.net>
10// - Henry de Valence <hdevalence@hdevalence.ca>
11
12//! Group operations for Curve25519, in Edwards form.
13//!
14//! ## Encoding and Decoding
15//!
16//! Encoding is done by converting to and from a `CompressedEdwardsY`
17//! struct, which is a typed wrapper around `[u8; 32]`.
18//!
19//! ## Equality Testing
20//!
21//! The `EdwardsPoint` struct implements the [`subtle::ConstantTimeEq`]
22//! trait for constant-time equality checking, and the Rust `Eq` trait
23//! for variable-time equality checking.
24//!
25//! ## Cofactor-related functions
26//!
27//! The order of the group of points on the curve \\(\mathcal E\\)
28//! is \\(|\mathcal E| = 8\ell \\), so its structure is \\( \mathcal
29//! E = \mathcal E\[8\] \times \mathcal E[\ell]\\).  The torsion
30//! subgroup \\( \mathcal E\[8\] \\) consists of eight points of small
31//! order.  Technically, all of \\(\mathcal E\\) is torsion, but we
32//! use the word only to refer to the small \\(\mathcal E\[8\]\\) part, not
33//! the large prime-order \\(\mathcal E[\ell]\\) part.
34//!
35//! To test if a point is in \\( \mathcal E\[8\] \\), use
36//! [`EdwardsPoint::is_small_order`].
37//!
38//! To test if a point is in \\( \mathcal E[\ell] \\), use
39//! [`EdwardsPoint::is_torsion_free`].
40//!
41//! To multiply by the cofactor, use [`EdwardsPoint::mul_by_cofactor`].
42//!
43//! To avoid dealing with cofactors entirely, consider using Ristretto.
44//!
45//! ## Scalars
46//!
47//! Scalars are represented by the [`Scalar`] struct. To construct a scalar, see
48//! [`Scalar::from_canonical_bytes`] or [`Scalar::from_bytes_mod_order_wide`].
49//!
50//! ## Scalar Multiplication
51//!
52//! Scalar multiplication on Edwards points is provided by:
53//!
54//! * the `*` operator between a `Scalar` and a `EdwardsPoint`, which
55//! performs constant-time variable-base scalar multiplication;
56//!
57//! * the `*` operator between a `Scalar` and a
58//! `EdwardsBasepointTable`, which performs constant-time fixed-base
59//! scalar multiplication;
60//!
61//! * an implementation of the
62//! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for
63//! constant-time variable-base multiscalar multiplication;
64//!
65//! * an implementation of the
66//! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html)
67//! trait for variable-time variable-base multiscalar multiplication;
68//!
69//! ## Implementation
70//!
71//! The Edwards arithmetic is implemented using the “extended twisted
72//! coordinates” of Hisil, Wong, Carter, and Dawson, and the
73//! corresponding complete formulas.  For more details,
74//! see the [`curve_models` submodule][curve_models]
75//! of the internal documentation.
76//!
77//! ## Validity Checking
78//!
79//! There is no function for checking whether a point is valid.
80//! Instead, the `EdwardsPoint` struct is guaranteed to hold a valid
81//! point on the curve.
82//!
83//! We use the Rust type system to make invalid points
84//! unrepresentable: `EdwardsPoint` objects can only be created via
85//! successful decompression of a compressed point, or else by
86//! operations on other (valid) `EdwardsPoint`s.
87//!
88//! [curve_models]: https://docs.rs/curve25519-dalek/latest/curve25519-dalek/backend/serial/curve_models/index.html
89
90// We allow non snake_case names because coordinates in projective space are
91// traditionally denoted by the capitalisation of their respective
92// counterparts in affine space.  Yeah, you heard me, rustc, I'm gonna have my
93// affine and projective cakes and eat both of them too.
94#![allow(non_snake_case)]
95
96use core::array::TryFromSliceError;
97use core::borrow::Borrow;
98use core::fmt::Debug;
99use core::iter::Sum;
100use core::ops::{Add, Neg, Sub};
101use core::ops::{AddAssign, SubAssign};
102use core::ops::{Mul, MulAssign};
103
104use cfg_if::cfg_if;
105
106#[cfg(feature = "digest")]
107use digest::{generic_array::typenum::U64, Digest};
108
109#[cfg(feature = "group")]
110use {
111    group::{cofactor::CofactorGroup, prime::PrimeGroup, GroupEncoding},
112    subtle::CtOption,
113};
114
115#[cfg(feature = "group")]
116use rand_core::RngCore;
117
118use subtle::Choice;
119use subtle::ConditionallyNegatable;
120use subtle::ConditionallySelectable;
121use subtle::ConstantTimeEq;
122
123#[cfg(feature = "zeroize")]
124use zeroize::Zeroize;
125
126use crate::constants;
127
128use crate::field::FieldElement;
129use crate::scalar::{clamp_integer, Scalar};
130
131use crate::montgomery::MontgomeryPoint;
132
133use crate::backend::serial::curve_models::AffineNielsPoint;
134use crate::backend::serial::curve_models::CompletedPoint;
135use crate::backend::serial::curve_models::ProjectiveNielsPoint;
136use crate::backend::serial::curve_models::ProjectivePoint;
137
138#[cfg(feature = "precomputed-tables")]
139use crate::window::{
140    LookupTableRadix128, LookupTableRadix16, LookupTableRadix256, LookupTableRadix32,
141    LookupTableRadix64,
142};
143
144#[cfg(feature = "precomputed-tables")]
145use crate::traits::BasepointTable;
146
147use crate::traits::ValidityCheck;
148use crate::traits::{Identity, IsIdentity};
149
150#[cfg(feature = "alloc")]
151use crate::traits::MultiscalarMul;
152#[cfg(feature = "alloc")]
153use crate::traits::{VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul};
154
155// ------------------------------------------------------------------------
156// Compressed points
157// ------------------------------------------------------------------------
158
159/// In "Edwards y" / "Ed25519" format, the curve point \\((x,y)\\) is
160/// determined by the \\(y\\)-coordinate and the sign of \\(x\\).
161///
162/// The first 255 bits of a `CompressedEdwardsY` represent the
163/// \\(y\\)-coordinate.  The high bit of the 32nd byte gives the sign of \\(x\\).
164#[derive(Copy, Clone, Eq, PartialEq, Hash)]
165pub struct CompressedEdwardsY(pub [u8; 32]);
166
167impl ConstantTimeEq for CompressedEdwardsY {
168    fn ct_eq(&self, other: &CompressedEdwardsY) -> Choice {
169        self.as_bytes().ct_eq(other.as_bytes())
170    }
171}
172
173impl Debug for CompressedEdwardsY {
174    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175        write!(f, "CompressedEdwardsY: {:?}", self.as_bytes())
176    }
177}
178
179impl CompressedEdwardsY {
180    /// View this `CompressedEdwardsY` as an array of bytes.
181    pub const fn as_bytes(&self) -> &[u8; 32] {
182        &self.0
183    }
184
185    /// Copy this `CompressedEdwardsY` to an array of bytes.
186    pub const fn to_bytes(&self) -> [u8; 32] {
187        self.0
188    }
189
190    /// Attempt to decompress to an `EdwardsPoint`.
191    ///
192    /// Returns `None` if the input is not the \\(y\\)-coordinate of a
193    /// curve point.
194    pub fn decompress(&self) -> Option<EdwardsPoint> {
195        let (is_valid_y_coord, X, Y, Z) = decompress::step_1(self);
196
197        if is_valid_y_coord.into() {
198            Some(decompress::step_2(self, X, Y, Z))
199        } else {
200            None
201        }
202    }
203}
204
205mod decompress {
206    use super::*;
207
208    #[rustfmt::skip] // keep alignment of explanatory comments
209    pub(super) fn step_1(
210        repr: &CompressedEdwardsY,
211    ) -> (Choice, FieldElement, FieldElement, FieldElement) {
212        let Y = FieldElement::from_bytes(repr.as_bytes());
213        let Z = FieldElement::ONE;
214        let YY = Y.square();
215        let u = &YY - &Z;                            // u =  y²-1
216        let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1
217        let (is_valid_y_coord, X) = FieldElement::sqrt_ratio_i(&u, &v);
218
219        (is_valid_y_coord, X, Y, Z)
220    }
221
222    #[rustfmt::skip]
223    pub(super) fn step_2(
224        repr: &CompressedEdwardsY,
225        mut X: FieldElement,
226        Y: FieldElement,
227        Z: FieldElement,
228    ) -> EdwardsPoint {
229         // FieldElement::sqrt_ratio_i always returns the nonnegative square root,
230         // so we negate according to the supplied sign bit.
231        let compressed_sign_bit = Choice::from(repr.as_bytes()[31] >> 7);
232        X.conditional_negate(compressed_sign_bit);
233
234        EdwardsPoint {
235            X,
236            Y,
237            Z,
238            T: &X * &Y,
239        }
240    }
241}
242
243impl TryFrom<&[u8]> for CompressedEdwardsY {
244    type Error = TryFromSliceError;
245
246    fn try_from(slice: &[u8]) -> Result<CompressedEdwardsY, TryFromSliceError> {
247        Self::from_slice(slice)
248    }
249}
250
251// ------------------------------------------------------------------------
252// Serde support
253// ------------------------------------------------------------------------
254// Serializes to and from `EdwardsPoint` directly, doing compression
255// and decompression internally.  This means that users can create
256// structs containing `EdwardsPoint`s and use Serde's derived
257// serializers to serialize those structures.
258
259#[cfg(feature = "serde")]
260use serde::de::Visitor;
261#[cfg(feature = "serde")]
262use serde::{Deserialize, Deserializer, Serialize, Serializer};
263
264#[cfg(feature = "serde")]
265impl Serialize for EdwardsPoint {
266    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
267    where
268        S: Serializer,
269    {
270        use serde::ser::SerializeTuple;
271        let mut tup = serializer.serialize_tuple(32)?;
272        for byte in self.compress().as_bytes().iter() {
273            tup.serialize_element(byte)?;
274        }
275        tup.end()
276    }
277}
278
279#[cfg(feature = "serde")]
280impl Serialize for CompressedEdwardsY {
281    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
282    where
283        S: Serializer,
284    {
285        use serde::ser::SerializeTuple;
286        let mut tup = serializer.serialize_tuple(32)?;
287        for byte in self.as_bytes().iter() {
288            tup.serialize_element(byte)?;
289        }
290        tup.end()
291    }
292}
293
294#[cfg(feature = "serde")]
295impl<'de> Deserialize<'de> for EdwardsPoint {
296    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297    where
298        D: Deserializer<'de>,
299    {
300        struct EdwardsPointVisitor;
301
302        impl<'de> Visitor<'de> for EdwardsPointVisitor {
303            type Value = EdwardsPoint;
304
305            fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
306                formatter.write_str("a valid point in Edwards y + sign format")
307            }
308
309            fn visit_seq<A>(self, mut seq: A) -> Result<EdwardsPoint, A::Error>
310            where
311                A: serde::de::SeqAccess<'de>,
312            {
313                let mut bytes = [0u8; 32];
314                #[allow(clippy::needless_range_loop)]
315                for i in 0..32 {
316                    bytes[i] = seq
317                        .next_element()?
318                        .ok_or_else(|| serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
319                }
320                CompressedEdwardsY(bytes)
321                    .decompress()
322                    .ok_or_else(|| serde::de::Error::custom("decompression failed"))
323            }
324        }
325
326        deserializer.deserialize_tuple(32, EdwardsPointVisitor)
327    }
328}
329
330#[cfg(feature = "serde")]
331impl<'de> Deserialize<'de> for CompressedEdwardsY {
332    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
333    where
334        D: Deserializer<'de>,
335    {
336        struct CompressedEdwardsYVisitor;
337
338        impl<'de> Visitor<'de> for CompressedEdwardsYVisitor {
339            type Value = CompressedEdwardsY;
340
341            fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
342                formatter.write_str("32 bytes of data")
343            }
344
345            fn visit_seq<A>(self, mut seq: A) -> Result<CompressedEdwardsY, A::Error>
346            where
347                A: serde::de::SeqAccess<'de>,
348            {
349                let mut bytes = [0u8; 32];
350                #[allow(clippy::needless_range_loop)]
351                for i in 0..32 {
352                    bytes[i] = seq
353                        .next_element()?
354                        .ok_or_else(|| serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
355                }
356                Ok(CompressedEdwardsY(bytes))
357            }
358        }
359
360        deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor)
361    }
362}
363
364// ------------------------------------------------------------------------
365// Internal point representations
366// ------------------------------------------------------------------------
367
368/// An `EdwardsPoint` represents a point on the Edwards form of Curve25519.
369#[derive(Copy, Clone)]
370#[allow(missing_docs)]
371pub struct EdwardsPoint {
372    pub(crate) X: FieldElement,
373    pub(crate) Y: FieldElement,
374    pub(crate) Z: FieldElement,
375    pub(crate) T: FieldElement,
376}
377
378// ------------------------------------------------------------------------
379// Constructors
380// ------------------------------------------------------------------------
381
382impl Identity for CompressedEdwardsY {
383    fn identity() -> CompressedEdwardsY {
384        CompressedEdwardsY([
385            1, 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,
386            0, 0, 0,
387        ])
388    }
389}
390
391impl Default for CompressedEdwardsY {
392    fn default() -> CompressedEdwardsY {
393        CompressedEdwardsY::identity()
394    }
395}
396
397impl CompressedEdwardsY {
398    /// Construct a `CompressedEdwardsY` from a slice of bytes.
399    ///
400    /// # Errors
401    ///
402    /// Returns [`TryFromSliceError`] if the input `bytes` slice does not have
403    /// a length of 32.
404    pub fn from_slice(bytes: &[u8]) -> Result<CompressedEdwardsY, TryFromSliceError> {
405        bytes.try_into().map(CompressedEdwardsY)
406    }
407}
408
409impl Identity for EdwardsPoint {
410    fn identity() -> EdwardsPoint {
411        EdwardsPoint {
412            X: FieldElement::ZERO,
413            Y: FieldElement::ONE,
414            Z: FieldElement::ONE,
415            T: FieldElement::ZERO,
416        }
417    }
418}
419
420impl Default for EdwardsPoint {
421    fn default() -> EdwardsPoint {
422        EdwardsPoint::identity()
423    }
424}
425
426// ------------------------------------------------------------------------
427// Zeroize implementations for wiping points from memory
428// ------------------------------------------------------------------------
429
430#[cfg(feature = "zeroize")]
431impl Zeroize for CompressedEdwardsY {
432    /// Reset this `CompressedEdwardsY` to the compressed form of the identity element.
433    fn zeroize(&mut self) {
434        self.0.zeroize();
435        self.0[0] = 1;
436    }
437}
438
439#[cfg(feature = "zeroize")]
440impl Zeroize for EdwardsPoint {
441    /// Reset this `CompressedEdwardsPoint` to the identity element.
442    fn zeroize(&mut self) {
443        self.X.zeroize();
444        self.Y = FieldElement::ONE;
445        self.Z = FieldElement::ONE;
446        self.T.zeroize();
447    }
448}
449
450// ------------------------------------------------------------------------
451// Validity checks (for debugging, not CT)
452// ------------------------------------------------------------------------
453
454impl ValidityCheck for EdwardsPoint {
455    fn is_valid(&self) -> bool {
456        let point_on_curve = self.as_projective().is_valid();
457        let on_segre_image = (&self.X * &self.Y) == (&self.Z * &self.T);
458
459        point_on_curve && on_segre_image
460    }
461}
462
463// ------------------------------------------------------------------------
464// Constant-time assignment
465// ------------------------------------------------------------------------
466
467impl ConditionallySelectable for EdwardsPoint {
468    fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint {
469        EdwardsPoint {
470            X: FieldElement::conditional_select(&a.X, &b.X, choice),
471            Y: FieldElement::conditional_select(&a.Y, &b.Y, choice),
472            Z: FieldElement::conditional_select(&a.Z, &b.Z, choice),
473            T: FieldElement::conditional_select(&a.T, &b.T, choice),
474        }
475    }
476}
477
478// ------------------------------------------------------------------------
479// Equality
480// ------------------------------------------------------------------------
481
482impl ConstantTimeEq for EdwardsPoint {
483    fn ct_eq(&self, other: &EdwardsPoint) -> Choice {
484        // We would like to check that the point (X/Z, Y/Z) is equal to
485        // the point (X'/Z', Y'/Z') without converting into affine
486        // coordinates (x, y) and (x', y'), which requires two inversions.
487        // We have that X = xZ and X' = x'Z'. Thus, x = x' is equivalent to
488        // (xZ)Z' = (x'Z')Z, and similarly for the y-coordinate.
489
490        (&self.X * &other.Z).ct_eq(&(&other.X * &self.Z))
491            & (&self.Y * &other.Z).ct_eq(&(&other.Y * &self.Z))
492    }
493}
494
495impl PartialEq for EdwardsPoint {
496    fn eq(&self, other: &EdwardsPoint) -> bool {
497        self.ct_eq(other).into()
498    }
499}
500
501impl Eq for EdwardsPoint {}
502
503// ------------------------------------------------------------------------
504// Point conversions
505// ------------------------------------------------------------------------
506
507impl EdwardsPoint {
508    /// Convert to a ProjectiveNielsPoint
509    pub(crate) fn as_projective_niels(&self) -> ProjectiveNielsPoint {
510        ProjectiveNielsPoint {
511            Y_plus_X: &self.Y + &self.X,
512            Y_minus_X: &self.Y - &self.X,
513            Z: self.Z,
514            T2d: &self.T * &constants::EDWARDS_D2,
515        }
516    }
517
518    /// Convert the representation of this point from extended
519    /// coordinates to projective coordinates.
520    ///
521    /// Free.
522    pub(crate) const fn as_projective(&self) -> ProjectivePoint {
523        ProjectivePoint {
524            X: self.X,
525            Y: self.Y,
526            Z: self.Z,
527        }
528    }
529
530    /// Dehomogenize to a AffineNielsPoint.
531    /// Mainly for testing.
532    pub(crate) fn as_affine_niels(&self) -> AffineNielsPoint {
533        let recip = self.Z.invert();
534        let x = &self.X * &recip;
535        let y = &self.Y * &recip;
536        let xy2d = &(&x * &y) * &constants::EDWARDS_D2;
537        AffineNielsPoint {
538            y_plus_x: &y + &x,
539            y_minus_x: &y - &x,
540            xy2d,
541        }
542    }
543
544    /// Convert this `EdwardsPoint` on the Edwards model to the
545    /// corresponding `MontgomeryPoint` on the Montgomery model.
546    ///
547    /// This function has one exceptional case; the identity point of
548    /// the Edwards curve is sent to the 2-torsion point \\((0,0)\\)
549    /// on the Montgomery curve.
550    ///
551    /// Note that this is a one-way conversion, since the Montgomery
552    /// model does not retain sign information.
553    pub fn to_montgomery(&self) -> MontgomeryPoint {
554        // We have u = (1+y)/(1-y) = (Z+Y)/(Z-Y).
555        //
556        // The denominator is zero only when y=1, the identity point of
557        // the Edwards curve.  Since 0.invert() = 0, in this case we
558        // compute the 2-torsion point (0,0).
559        let U = &self.Z + &self.Y;
560        let W = &self.Z - &self.Y;
561        let u = &U * &W.invert();
562        MontgomeryPoint(u.as_bytes())
563    }
564
565    /// Compress this point to `CompressedEdwardsY` format.
566    pub fn compress(&self) -> CompressedEdwardsY {
567        let recip = self.Z.invert();
568        let x = &self.X * &recip;
569        let y = &self.Y * &recip;
570        let mut s: [u8; 32];
571
572        s = y.as_bytes();
573        s[31] ^= x.is_negative().unwrap_u8() << 7;
574        CompressedEdwardsY(s)
575    }
576
577    #[cfg(feature = "digest")]
578    /// Maps the digest of the input bytes to the curve. This is NOT a hash-to-curve function, as
579    /// it produces points with a non-uniform distribution. Rather, it performs something that
580    /// resembles (but is not) half of the
581    /// [`hash_to_curve`](https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#section-3-4.2.1)
582    /// function from the Elligator2 spec.
583    #[deprecated(
584        since = "4.0.0",
585        note = "previously named `hash_from_bytes`, this is not a secure hash function"
586    )]
587    pub fn nonspec_map_to_curve<D>(bytes: &[u8]) -> EdwardsPoint
588    where
589        D: Digest<OutputSize = U64> + Default,
590    {
591        let mut hash = D::new();
592        hash.update(bytes);
593        let h = hash.finalize();
594        let mut res = [0u8; 32];
595        res.copy_from_slice(&h[..32]);
596
597        let sign_bit = (res[31] & 0x80) >> 7;
598
599        let fe = FieldElement::from_bytes(&res);
600
601        let M1 = crate::montgomery::elligator_encode(&fe);
602        let E1_opt = M1.to_edwards(sign_bit);
603
604        E1_opt
605            .expect("Montgomery conversion to Edwards point in Elligator failed")
606            .mul_by_cofactor()
607    }
608}
609
610// ------------------------------------------------------------------------
611// Doubling
612// ------------------------------------------------------------------------
613
614impl EdwardsPoint {
615    /// Add this point to itself.
616    pub(crate) fn double(&self) -> EdwardsPoint {
617        self.as_projective().double().as_extended()
618    }
619}
620
621// ------------------------------------------------------------------------
622// Addition and Subtraction
623// ------------------------------------------------------------------------
624
625impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint {
626    type Output = EdwardsPoint;
627    fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint {
628        (self + &other.as_projective_niels()).as_extended()
629    }
630}
631
632define_add_variants!(
633    LHS = EdwardsPoint,
634    RHS = EdwardsPoint,
635    Output = EdwardsPoint
636);
637
638impl<'b> AddAssign<&'b EdwardsPoint> for EdwardsPoint {
639    fn add_assign(&mut self, _rhs: &'b EdwardsPoint) {
640        *self = (self as &EdwardsPoint) + _rhs;
641    }
642}
643
644define_add_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint);
645
646impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint {
647    type Output = EdwardsPoint;
648    fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint {
649        (self - &other.as_projective_niels()).as_extended()
650    }
651}
652
653define_sub_variants!(
654    LHS = EdwardsPoint,
655    RHS = EdwardsPoint,
656    Output = EdwardsPoint
657);
658
659impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint {
660    fn sub_assign(&mut self, _rhs: &'b EdwardsPoint) {
661        *self = (self as &EdwardsPoint) - _rhs;
662    }
663}
664
665define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint);
666
667impl<T> Sum<T> for EdwardsPoint
668where
669    T: Borrow<EdwardsPoint>,
670{
671    fn sum<I>(iter: I) -> Self
672    where
673        I: Iterator<Item = T>,
674    {
675        iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow())
676    }
677}
678
679// ------------------------------------------------------------------------
680// Negation
681// ------------------------------------------------------------------------
682
683impl<'a> Neg for &'a EdwardsPoint {
684    type Output = EdwardsPoint;
685
686    fn neg(self) -> EdwardsPoint {
687        EdwardsPoint {
688            X: -(&self.X),
689            Y: self.Y,
690            Z: self.Z,
691            T: -(&self.T),
692        }
693    }
694}
695
696impl Neg for EdwardsPoint {
697    type Output = EdwardsPoint;
698
699    fn neg(self) -> EdwardsPoint {
700        -&self
701    }
702}
703
704// ------------------------------------------------------------------------
705// Scalar multiplication
706// ------------------------------------------------------------------------
707
708impl<'b> MulAssign<&'b Scalar> for EdwardsPoint {
709    fn mul_assign(&mut self, scalar: &'b Scalar) {
710        let result = (self as &EdwardsPoint) * scalar;
711        *self = result;
712    }
713}
714
715define_mul_assign_variants!(LHS = EdwardsPoint, RHS = Scalar);
716
717define_mul_variants!(LHS = EdwardsPoint, RHS = Scalar, Output = EdwardsPoint);
718define_mul_variants!(LHS = Scalar, RHS = EdwardsPoint, Output = EdwardsPoint);
719
720impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint {
721    type Output = EdwardsPoint;
722    /// Scalar multiplication: compute `scalar * self`.
723    ///
724    /// For scalar multiplication of a basepoint,
725    /// `EdwardsBasepointTable` is approximately 4x faster.
726    fn mul(self, scalar: &'b Scalar) -> EdwardsPoint {
727        crate::backend::variable_base_mul(self, scalar)
728    }
729}
730
731impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar {
732    type Output = EdwardsPoint;
733
734    /// Scalar multiplication: compute `scalar * self`.
735    ///
736    /// For scalar multiplication of a basepoint,
737    /// `EdwardsBasepointTable` is approximately 4x faster.
738    fn mul(self, point: &'b EdwardsPoint) -> EdwardsPoint {
739        point * self
740    }
741}
742
743impl EdwardsPoint {
744    /// Fixed-base scalar multiplication by the Ed25519 base point.
745    ///
746    /// Uses precomputed basepoint tables when the `precomputed-tables` feature
747    /// is enabled, trading off increased code size for ~4x better performance.
748    pub fn mul_base(scalar: &Scalar) -> Self {
749        #[cfg(not(feature = "precomputed-tables"))]
750        {
751            scalar * constants::ED25519_BASEPOINT_POINT
752        }
753
754        #[cfg(feature = "precomputed-tables")]
755        {
756            scalar * constants::ED25519_BASEPOINT_TABLE
757        }
758    }
759
760    /// Multiply this point by `clamp_integer(bytes)`. For a description of clamping, see
761    /// [`clamp_integer`].
762    pub fn mul_clamped(self, bytes: [u8; 32]) -> Self {
763        // We have to construct a Scalar that is not reduced mod l, which breaks scalar invariant
764        // #2. But #2 is not necessary for correctness of variable-base multiplication. All that
765        // needs to hold is invariant #1, i.e., the scalar is less than 2^255. This is guaranteed
766        // by clamping.
767        // Further, we don't do any reduction or arithmetic with this clamped value, so there's no
768        // issues arising from the fact that the curve point is not necessarily in the prime-order
769        // subgroup.
770        let s = Scalar {
771            bytes: clamp_integer(bytes),
772        };
773        s * self
774    }
775
776    /// Multiply the basepoint by `clamp_integer(bytes)`. For a description of clamping, see
777    /// [`clamp_integer`].
778    pub fn mul_base_clamped(bytes: [u8; 32]) -> Self {
779        // See reasoning in Self::mul_clamped why it is OK to make an unreduced Scalar here. We
780        // note that fixed-base multiplication is also defined for all values of `bytes` less than
781        // 2^255.
782        let s = Scalar {
783            bytes: clamp_integer(bytes),
784        };
785        Self::mul_base(&s)
786    }
787}
788
789// ------------------------------------------------------------------------
790// Multiscalar Multiplication impls
791// ------------------------------------------------------------------------
792
793// These use the iterator's size hint and the target settings to
794// forward to a specific backend implementation.
795
796#[cfg(feature = "alloc")]
797impl MultiscalarMul for EdwardsPoint {
798    type Point = EdwardsPoint;
799
800    fn multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint
801    where
802        I: IntoIterator,
803        I::Item: Borrow<Scalar>,
804        J: IntoIterator,
805        J::Item: Borrow<EdwardsPoint>,
806    {
807        // Sanity-check lengths of input iterators
808        let mut scalars = scalars.into_iter();
809        let mut points = points.into_iter();
810
811        // Lower and upper bounds on iterators
812        let (s_lo, s_hi) = scalars.by_ref().size_hint();
813        let (p_lo, p_hi) = points.by_ref().size_hint();
814
815        // They should all be equal
816        assert_eq!(s_lo, p_lo);
817        assert_eq!(s_hi, Some(s_lo));
818        assert_eq!(p_hi, Some(p_lo));
819
820        // Now we know there's a single size.  When we do
821        // size-dependent algorithm dispatch, use this as the hint.
822        let _size = s_lo;
823
824        crate::backend::straus_multiscalar_mul(scalars, points)
825    }
826}
827
828#[cfg(feature = "alloc")]
829impl VartimeMultiscalarMul for EdwardsPoint {
830    type Point = EdwardsPoint;
831
832    fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint>
833    where
834        I: IntoIterator,
835        I::Item: Borrow<Scalar>,
836        J: IntoIterator<Item = Option<EdwardsPoint>>,
837    {
838        // Sanity-check lengths of input iterators
839        let mut scalars = scalars.into_iter();
840        let mut points = points.into_iter();
841
842        // Lower and upper bounds on iterators
843        let (s_lo, s_hi) = scalars.by_ref().size_hint();
844        let (p_lo, p_hi) = points.by_ref().size_hint();
845
846        // They should all be equal
847        assert_eq!(s_lo, p_lo);
848        assert_eq!(s_hi, Some(s_lo));
849        assert_eq!(p_hi, Some(p_lo));
850
851        // Now we know there's a single size.
852        // Use this as the hint to decide which algorithm to use.
853        let size = s_lo;
854
855        if size < 190 {
856            crate::backend::straus_optional_multiscalar_mul(scalars, points)
857        } else {
858            crate::backend::pippenger_optional_multiscalar_mul(scalars, points)
859        }
860    }
861}
862
863/// Precomputation for variable-time multiscalar multiplication with `EdwardsPoint`s.
864// This wraps the inner implementation in a facade type so that we can
865// decouple stability of the inner type from the stability of the
866// outer type.
867#[cfg(feature = "alloc")]
868pub struct VartimeEdwardsPrecomputation(crate::backend::VartimePrecomputedStraus);
869
870#[cfg(feature = "alloc")]
871impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation {
872    type Point = EdwardsPoint;
873
874    fn new<I>(static_points: I) -> Self
875    where
876        I: IntoIterator,
877        I::Item: Borrow<Self::Point>,
878    {
879        Self(crate::backend::VartimePrecomputedStraus::new(static_points))
880    }
881
882    fn optional_mixed_multiscalar_mul<I, J, K>(
883        &self,
884        static_scalars: I,
885        dynamic_scalars: J,
886        dynamic_points: K,
887    ) -> Option<Self::Point>
888    where
889        I: IntoIterator,
890        I::Item: Borrow<Scalar>,
891        J: IntoIterator,
892        J::Item: Borrow<Scalar>,
893        K: IntoIterator<Item = Option<Self::Point>>,
894    {
895        self.0
896            .optional_mixed_multiscalar_mul(static_scalars, dynamic_scalars, dynamic_points)
897    }
898}
899
900impl EdwardsPoint {
901    /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
902    pub fn vartime_double_scalar_mul_basepoint(
903        a: &Scalar,
904        A: &EdwardsPoint,
905        b: &Scalar,
906    ) -> EdwardsPoint {
907        crate::backend::vartime_double_base_mul(a, A, b)
908    }
909}
910
911#[cfg(feature = "precomputed-tables")]
912macro_rules! impl_basepoint_table {
913    (Name = $name:ident, LookupTable = $table:ident, Point = $point:ty, Radix = $radix:expr, Additions = $adds:expr) => {
914        /// A precomputed table of multiples of a basepoint, for accelerating
915        /// fixed-base scalar multiplication.  One table, for the Ed25519
916        /// basepoint, is provided in the [`constants`] module.
917        ///
918        /// The basepoint tables are reasonably large, so they should probably be boxed.
919        ///
920        /// The sizes for the tables and the number of additions required for one scalar
921        /// multiplication are as follows:
922        ///
923        /// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A
924        ///   (this is the default size, and is used for
925        ///   [`constants::ED25519_BASEPOINT_TABLE`])
926        /// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A
927        /// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A
928        /// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A
929        ///
930        /// # Why 33 additions for radix-256?
931        ///
932        /// Normally, the radix-256 tables would allow for only 32 additions per scalar
933        /// multiplication.  However, due to the fact that standardised definitions of
934        /// legacy protocols—such as x25519—require allowing unreduced 255-bit scalars
935        /// invariants, when converting such an unreduced scalar's representation to
936        /// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last
937        /// coefficient (the coefficients are `i8`s).  When, \\(w\\), the power-of-2 of
938        /// the radix, is \\(w < 8\\), we can fold the final carry onto the last
939        /// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so
940        /// $$
941        ///     d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8}
942        /// $$
943        /// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we
944        /// add the carry bit onto an additional coefficient.
945        #[derive(Clone)]
946        #[repr(transparent)]
947        pub struct $name(pub(crate) [$table<AffineNielsPoint>; 32]);
948
949        impl BasepointTable for $name {
950            type Point = $point;
951
952            /// Create a table of precomputed multiples of `basepoint`.
953            fn create(basepoint: &$point) -> $name {
954                // XXX use init_with
955                let mut table = $name([$table::default(); 32]);
956                let mut P = *basepoint;
957                for i in 0..32 {
958                    // P = (2w)^i * B
959                    table.0[i] = $table::from(&P);
960                    P = P.mul_by_pow_2($radix + $radix);
961                }
962                table
963            }
964
965            /// Get the basepoint for this table as an `EdwardsPoint`.
966            fn basepoint(&self) -> $point {
967                // self.0[0].select(1) = 1*(16^2)^0*B
968                // but as an `AffineNielsPoint`, so add identity to convert to extended.
969                (&<$point>::identity() + &self.0[0].select(1)).as_extended()
970            }
971
972            /// The computation uses Pippeneger's algorithm, as described for the
973            /// specific case of radix-16 on page 13 of the Ed25519 paper.
974            ///
975            /// # Piggenger's Algorithm Generalised
976            ///
977            /// Write the scalar \\(a\\) in radix-\\(w\\), where \\(w\\) is a power of
978            /// 2, with coefficients in \\([\frac{-w}{2},\frac{w}{2})\\), i.e.,
979            /// $$
980            ///     a = a\_0 + a\_1 w\^1 + \cdots + a\_{x} w\^{x},
981            /// $$
982            /// with
983            /// $$
984            /// \begin{aligned}
985            ///     \frac{-w}{2} \leq a_i < \frac{w}{2}
986            ///     &&\cdots&&
987            ///     \frac{-w}{2} \leq a\_{x} \leq \frac{w}{2}
988            /// \end{aligned}
989            /// $$
990            /// and the number of additions, \\(x\\), is given by
991            /// \\(x = \lceil \frac{256}{w} \rceil\\). Then
992            /// $$
993            ///     a B = a\_0 B + a\_1 w\^1 B + \cdots + a\_{x-1} w\^{x-1} B.
994            /// $$
995            /// Grouping even and odd coefficients gives
996            /// $$
997            /// \begin{aligned}
998            ///     a B = \quad a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B    \\\\
999            ///               + a\_1 w\^1 B +& a\_3 w\^3 B + \cdots + a\_{x-1} w\^{x-1} B    \\\\
1000            ///         = \quad(a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B)   \\\\
1001            ///             + w(a\_1 w\^0 B +& a\_3 w\^2 B + \cdots + a\_{x-1} w\^{x-2} B).  \\\\
1002            /// \end{aligned}
1003            /// $$
1004            /// For each \\(i = 0 \ldots 31\\), we create a lookup table of
1005            /// $$
1006            /// [w\^{2i} B, \ldots, \frac{w}{2}\cdot w\^{2i} B],
1007            /// $$
1008            /// and use it to select \\( y \cdot w\^{2i} \cdot B \\) in constant time.
1009            ///
1010            /// The radix-\\(w\\) representation requires that the scalar is bounded
1011            /// by \\(2\^{255}\\), which is always the case.
1012            ///
1013            /// The above algorithm is trivially generalised to other powers-of-2 radices.
1014            fn mul_base(&self, scalar: &Scalar) -> $point {
1015                let a = scalar.as_radix_2w($radix);
1016
1017                let tables = &self.0;
1018                let mut P = <$point>::identity();
1019
1020                for i in (0..$adds).filter(|x| x % 2 == 1) {
1021                    P = (&P + &tables[i / 2].select(a[i])).as_extended();
1022                }
1023
1024                P = P.mul_by_pow_2($radix);
1025
1026                for i in (0..$adds).filter(|x| x % 2 == 0) {
1027                    P = (&P + &tables[i / 2].select(a[i])).as_extended();
1028                }
1029
1030                P
1031            }
1032        }
1033
1034        impl<'a, 'b> Mul<&'b Scalar> for &'a $name {
1035            type Output = $point;
1036
1037            /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
1038            /// computing the multiple \\(aB\\) of this basepoint \\(B\\).
1039            fn mul(self, scalar: &'b Scalar) -> $point {
1040                // delegate to a private function so that its documentation appears in internal docs
1041                self.mul_base(scalar)
1042            }
1043        }
1044
1045        impl<'a, 'b> Mul<&'a $name> for &'b Scalar {
1046            type Output = $point;
1047
1048            /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
1049            /// computing the multiple \\(aB\\) of this basepoint \\(B\\).
1050            fn mul(self, basepoint_table: &'a $name) -> $point {
1051                basepoint_table * self
1052            }
1053        }
1054
1055        impl Debug for $name {
1056            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1057                write!(f, "{:?}([\n", stringify!($name))?;
1058                for i in 0..32 {
1059                    write!(f, "\t{:?},\n", &self.0[i])?;
1060                }
1061                write!(f, "])")
1062            }
1063        }
1064    };
1065} // End macro_rules! impl_basepoint_table
1066
1067// The number of additions required is ceil(256/w) where w is the radix representation.
1068cfg_if! {
1069    if #[cfg(feature = "precomputed-tables")] {
1070        impl_basepoint_table! {
1071            Name = EdwardsBasepointTable,
1072            LookupTable = LookupTableRadix16,
1073            Point = EdwardsPoint,
1074            Radix = 4,
1075            Additions = 64
1076        }
1077        impl_basepoint_table! {
1078            Name = EdwardsBasepointTableRadix32,
1079            LookupTable = LookupTableRadix32,
1080            Point = EdwardsPoint,
1081            Radix = 5,
1082            Additions = 52
1083        }
1084        impl_basepoint_table! {
1085            Name = EdwardsBasepointTableRadix64,
1086            LookupTable = LookupTableRadix64,
1087            Point = EdwardsPoint,
1088            Radix = 6,
1089            Additions = 43
1090        }
1091        impl_basepoint_table! {
1092            Name = EdwardsBasepointTableRadix128,
1093            LookupTable = LookupTableRadix128,
1094            Point = EdwardsPoint,
1095            Radix = 7,
1096            Additions = 37
1097        }
1098        impl_basepoint_table! {
1099            Name = EdwardsBasepointTableRadix256,
1100            LookupTable = LookupTableRadix256,
1101            Point = EdwardsPoint,
1102            Radix = 8,
1103            Additions = 33
1104        }
1105
1106        /// A type-alias for [`EdwardsBasepointTable`] because the latter is
1107        /// used as a constructor in the [`constants`] module.
1108        //
1109        // Same as for `LookupTableRadix16`, we have to define `EdwardsBasepointTable`
1110        // first, because it's used as a constructor, and then provide a type alias for
1111        // it.
1112        pub type EdwardsBasepointTableRadix16 = EdwardsBasepointTable;
1113    }
1114}
1115
1116#[cfg(feature = "precomputed-tables")]
1117macro_rules! impl_basepoint_table_conversions {
1118    (LHS = $lhs:ty, RHS = $rhs:ty) => {
1119        impl<'a> From<&'a $lhs> for $rhs {
1120            fn from(table: &'a $lhs) -> $rhs {
1121                <$rhs>::create(&table.basepoint())
1122            }
1123        }
1124
1125        impl<'a> From<&'a $rhs> for $lhs {
1126            fn from(table: &'a $rhs) -> $lhs {
1127                <$lhs>::create(&table.basepoint())
1128            }
1129        }
1130    };
1131}
1132
1133cfg_if! {
1134    if #[cfg(feature = "precomputed-tables")] {
1135        // Conversions from radix 16
1136        impl_basepoint_table_conversions! {
1137            LHS = EdwardsBasepointTableRadix16,
1138            RHS = EdwardsBasepointTableRadix32
1139        }
1140        impl_basepoint_table_conversions! {
1141            LHS = EdwardsBasepointTableRadix16,
1142            RHS = EdwardsBasepointTableRadix64
1143        }
1144        impl_basepoint_table_conversions! {
1145            LHS = EdwardsBasepointTableRadix16,
1146            RHS = EdwardsBasepointTableRadix128
1147        }
1148        impl_basepoint_table_conversions! {
1149            LHS = EdwardsBasepointTableRadix16,
1150            RHS = EdwardsBasepointTableRadix256
1151        }
1152
1153        // Conversions from radix 32
1154        impl_basepoint_table_conversions! {
1155            LHS = EdwardsBasepointTableRadix32,
1156            RHS = EdwardsBasepointTableRadix64
1157        }
1158        impl_basepoint_table_conversions! {
1159            LHS = EdwardsBasepointTableRadix32,
1160            RHS = EdwardsBasepointTableRadix128
1161        }
1162        impl_basepoint_table_conversions! {
1163            LHS = EdwardsBasepointTableRadix32,
1164            RHS = EdwardsBasepointTableRadix256
1165        }
1166
1167        // Conversions from radix 64
1168        impl_basepoint_table_conversions! {
1169            LHS = EdwardsBasepointTableRadix64,
1170            RHS = EdwardsBasepointTableRadix128
1171        }
1172        impl_basepoint_table_conversions! {
1173            LHS = EdwardsBasepointTableRadix64,
1174            RHS = EdwardsBasepointTableRadix256
1175        }
1176
1177        // Conversions from radix 128
1178        impl_basepoint_table_conversions! {
1179            LHS = EdwardsBasepointTableRadix128,
1180            RHS = EdwardsBasepointTableRadix256
1181        }
1182    }
1183}
1184
1185impl EdwardsPoint {
1186    /// Multiply by the cofactor: return \\(\[8\]P\\).
1187    pub fn mul_by_cofactor(&self) -> EdwardsPoint {
1188        self.mul_by_pow_2(3)
1189    }
1190
1191    /// Compute \\([2\^k] P \\) by successive doublings. Requires \\( k > 0 \\).
1192    pub(crate) fn mul_by_pow_2(&self, k: u32) -> EdwardsPoint {
1193        debug_assert!(k > 0);
1194        let mut r: CompletedPoint;
1195        let mut s = self.as_projective();
1196        for _ in 0..(k - 1) {
1197            r = s.double();
1198            s = r.as_projective();
1199        }
1200        // Unroll last iteration so we can go directly as_extended()
1201        s.double().as_extended()
1202    }
1203
1204    /// Determine if this point is of small order.
1205    ///
1206    /// # Return
1207    ///
1208    /// * `true` if `self` is in the torsion subgroup \\( \mathcal E\[8\] \\);
1209    /// * `false` if `self` is not in the torsion subgroup \\( \mathcal E\[8\] \\).
1210    ///
1211    /// # Example
1212    ///
1213    /// ```
1214    /// use curve25519_dalek::constants;
1215    ///
1216    /// // Generator of the prime-order subgroup
1217    /// let P = constants::ED25519_BASEPOINT_POINT;
1218    /// // Generator of the torsion subgroup
1219    /// let Q = constants::EIGHT_TORSION[1];
1220    ///
1221    /// // P has large order
1222    /// assert_eq!(P.is_small_order(), false);
1223    ///
1224    /// // Q has small order
1225    /// assert_eq!(Q.is_small_order(), true);
1226    /// ```
1227    pub fn is_small_order(&self) -> bool {
1228        self.mul_by_cofactor().is_identity()
1229    }
1230
1231    /// Determine if this point is “torsion-free”, i.e., is contained in
1232    /// the prime-order subgroup.
1233    ///
1234    /// # Return
1235    ///
1236    /// * `true` if `self` has zero torsion component and is in the
1237    /// prime-order subgroup;
1238    /// * `false` if `self` has a nonzero torsion component and is not
1239    /// in the prime-order subgroup.
1240    ///
1241    /// # Example
1242    ///
1243    /// ```
1244    /// use curve25519_dalek::constants;
1245    ///
1246    /// // Generator of the prime-order subgroup
1247    /// let P = constants::ED25519_BASEPOINT_POINT;
1248    /// // Generator of the torsion subgroup
1249    /// let Q = constants::EIGHT_TORSION[1];
1250    ///
1251    /// // P is torsion-free
1252    /// assert_eq!(P.is_torsion_free(), true);
1253    ///
1254    /// // P + Q is not torsion-free
1255    /// assert_eq!((P+Q).is_torsion_free(), false);
1256    /// ```
1257    pub fn is_torsion_free(&self) -> bool {
1258        (self * constants::BASEPOINT_ORDER_PRIVATE).is_identity()
1259    }
1260}
1261
1262// ------------------------------------------------------------------------
1263// Debug traits
1264// ------------------------------------------------------------------------
1265
1266impl Debug for EdwardsPoint {
1267    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1268        write!(
1269            f,
1270            "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}",
1271            &self.X, &self.Y, &self.Z, &self.T
1272        )
1273    }
1274}
1275
1276// ------------------------------------------------------------------------
1277// group traits
1278// ------------------------------------------------------------------------
1279
1280// Use the full trait path to avoid Group::identity overlapping Identity::identity in the
1281// rest of the module (e.g. tests).
1282#[cfg(feature = "group")]
1283impl group::Group for EdwardsPoint {
1284    type Scalar = Scalar;
1285
1286    fn random(mut rng: impl RngCore) -> Self {
1287        let mut repr = CompressedEdwardsY([0u8; 32]);
1288        loop {
1289            rng.fill_bytes(&mut repr.0);
1290            if let Some(p) = repr.decompress() {
1291                if !IsIdentity::is_identity(&p) {
1292                    break p;
1293                }
1294            }
1295        }
1296    }
1297
1298    fn identity() -> Self {
1299        Identity::identity()
1300    }
1301
1302    fn generator() -> Self {
1303        constants::ED25519_BASEPOINT_POINT
1304    }
1305
1306    fn is_identity(&self) -> Choice {
1307        self.ct_eq(&Identity::identity())
1308    }
1309
1310    fn double(&self) -> Self {
1311        self.double()
1312    }
1313}
1314
1315#[cfg(feature = "group")]
1316impl GroupEncoding for EdwardsPoint {
1317    type Repr = [u8; 32];
1318
1319    fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
1320        let repr = CompressedEdwardsY(*bytes);
1321        let (is_valid_y_coord, X, Y, Z) = decompress::step_1(&repr);
1322        CtOption::new(decompress::step_2(&repr, X, Y, Z), is_valid_y_coord)
1323    }
1324
1325    fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
1326        // Just use the checked API; there are no checks we can skip.
1327        Self::from_bytes(bytes)
1328    }
1329
1330    fn to_bytes(&self) -> Self::Repr {
1331        self.compress().to_bytes()
1332    }
1333}
1334
1335/// A `SubgroupPoint` represents a point on the Edwards form of Curve25519, that is
1336/// guaranteed to be in the prime-order subgroup.
1337#[cfg(feature = "group")]
1338#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1339pub struct SubgroupPoint(EdwardsPoint);
1340
1341#[cfg(feature = "group")]
1342impl From<SubgroupPoint> for EdwardsPoint {
1343    fn from(p: SubgroupPoint) -> Self {
1344        p.0
1345    }
1346}
1347
1348#[cfg(feature = "group")]
1349impl Neg for SubgroupPoint {
1350    type Output = Self;
1351
1352    fn neg(self) -> Self::Output {
1353        SubgroupPoint(-self.0)
1354    }
1355}
1356
1357#[cfg(feature = "group")]
1358impl Add<&SubgroupPoint> for &SubgroupPoint {
1359    type Output = SubgroupPoint;
1360    fn add(self, other: &SubgroupPoint) -> SubgroupPoint {
1361        SubgroupPoint(self.0 + other.0)
1362    }
1363}
1364
1365#[cfg(feature = "group")]
1366define_add_variants!(
1367    LHS = SubgroupPoint,
1368    RHS = SubgroupPoint,
1369    Output = SubgroupPoint
1370);
1371
1372#[cfg(feature = "group")]
1373impl Add<&SubgroupPoint> for &EdwardsPoint {
1374    type Output = EdwardsPoint;
1375    fn add(self, other: &SubgroupPoint) -> EdwardsPoint {
1376        self + other.0
1377    }
1378}
1379
1380#[cfg(feature = "group")]
1381define_add_variants!(
1382    LHS = EdwardsPoint,
1383    RHS = SubgroupPoint,
1384    Output = EdwardsPoint
1385);
1386
1387#[cfg(feature = "group")]
1388impl AddAssign<&SubgroupPoint> for SubgroupPoint {
1389    fn add_assign(&mut self, rhs: &SubgroupPoint) {
1390        self.0 += rhs.0
1391    }
1392}
1393
1394#[cfg(feature = "group")]
1395define_add_assign_variants!(LHS = SubgroupPoint, RHS = SubgroupPoint);
1396
1397#[cfg(feature = "group")]
1398impl AddAssign<&SubgroupPoint> for EdwardsPoint {
1399    fn add_assign(&mut self, rhs: &SubgroupPoint) {
1400        *self += rhs.0
1401    }
1402}
1403
1404#[cfg(feature = "group")]
1405define_add_assign_variants!(LHS = EdwardsPoint, RHS = SubgroupPoint);
1406
1407#[cfg(feature = "group")]
1408impl Sub<&SubgroupPoint> for &SubgroupPoint {
1409    type Output = SubgroupPoint;
1410    fn sub(self, other: &SubgroupPoint) -> SubgroupPoint {
1411        SubgroupPoint(self.0 - other.0)
1412    }
1413}
1414
1415#[cfg(feature = "group")]
1416define_sub_variants!(
1417    LHS = SubgroupPoint,
1418    RHS = SubgroupPoint,
1419    Output = SubgroupPoint
1420);
1421
1422#[cfg(feature = "group")]
1423impl Sub<&SubgroupPoint> for &EdwardsPoint {
1424    type Output = EdwardsPoint;
1425    fn sub(self, other: &SubgroupPoint) -> EdwardsPoint {
1426        self - other.0
1427    }
1428}
1429
1430#[cfg(feature = "group")]
1431define_sub_variants!(
1432    LHS = EdwardsPoint,
1433    RHS = SubgroupPoint,
1434    Output = EdwardsPoint
1435);
1436
1437#[cfg(feature = "group")]
1438impl SubAssign<&SubgroupPoint> for SubgroupPoint {
1439    fn sub_assign(&mut self, rhs: &SubgroupPoint) {
1440        self.0 -= rhs.0;
1441    }
1442}
1443
1444#[cfg(feature = "group")]
1445define_sub_assign_variants!(LHS = SubgroupPoint, RHS = SubgroupPoint);
1446
1447#[cfg(feature = "group")]
1448impl SubAssign<&SubgroupPoint> for EdwardsPoint {
1449    fn sub_assign(&mut self, rhs: &SubgroupPoint) {
1450        *self -= rhs.0;
1451    }
1452}
1453
1454#[cfg(feature = "group")]
1455define_sub_assign_variants!(LHS = EdwardsPoint, RHS = SubgroupPoint);
1456
1457#[cfg(feature = "group")]
1458impl<T> Sum<T> for SubgroupPoint
1459where
1460    T: Borrow<SubgroupPoint>,
1461{
1462    fn sum<I>(iter: I) -> Self
1463    where
1464        I: Iterator<Item = T>,
1465    {
1466        use group::Group;
1467        iter.fold(SubgroupPoint::identity(), |acc, item| acc + item.borrow())
1468    }
1469}
1470
1471#[cfg(feature = "group")]
1472impl Mul<&Scalar> for &SubgroupPoint {
1473    type Output = SubgroupPoint;
1474
1475    /// Scalar multiplication: compute `scalar * self`.
1476    ///
1477    /// For scalar multiplication of a basepoint,
1478    /// `EdwardsBasepointTable` is approximately 4x faster.
1479    fn mul(self, scalar: &Scalar) -> SubgroupPoint {
1480        SubgroupPoint(self.0 * scalar)
1481    }
1482}
1483
1484#[cfg(feature = "group")]
1485define_mul_variants!(LHS = Scalar, RHS = SubgroupPoint, Output = SubgroupPoint);
1486
1487#[cfg(feature = "group")]
1488impl Mul<&SubgroupPoint> for &Scalar {
1489    type Output = SubgroupPoint;
1490
1491    /// Scalar multiplication: compute `scalar * self`.
1492    ///
1493    /// For scalar multiplication of a basepoint,
1494    /// `EdwardsBasepointTable` is approximately 4x faster.
1495    fn mul(self, point: &SubgroupPoint) -> SubgroupPoint {
1496        point * self
1497    }
1498}
1499
1500#[cfg(feature = "group")]
1501define_mul_variants!(LHS = SubgroupPoint, RHS = Scalar, Output = SubgroupPoint);
1502
1503#[cfg(feature = "group")]
1504impl MulAssign<&Scalar> for SubgroupPoint {
1505    fn mul_assign(&mut self, scalar: &Scalar) {
1506        self.0 *= scalar;
1507    }
1508}
1509
1510#[cfg(feature = "group")]
1511define_mul_assign_variants!(LHS = SubgroupPoint, RHS = Scalar);
1512
1513#[cfg(feature = "group")]
1514impl group::Group for SubgroupPoint {
1515    type Scalar = Scalar;
1516
1517    fn random(mut rng: impl RngCore) -> Self {
1518        use group::ff::Field;
1519
1520        // This will almost never loop, but `Group::random` is documented as returning a
1521        // non-identity element.
1522        let s = loop {
1523            let s: Scalar = Field::random(&mut rng);
1524            if !s.is_zero_vartime() {
1525                break s;
1526            }
1527        };
1528
1529        // This gives an element of the prime-order subgroup.
1530        Self::generator() * s
1531    }
1532
1533    fn identity() -> Self {
1534        SubgroupPoint(Identity::identity())
1535    }
1536
1537    fn generator() -> Self {
1538        SubgroupPoint(EdwardsPoint::generator())
1539    }
1540
1541    fn is_identity(&self) -> Choice {
1542        self.0.ct_eq(&Identity::identity())
1543    }
1544
1545    fn double(&self) -> Self {
1546        SubgroupPoint(self.0.double())
1547    }
1548}
1549
1550#[cfg(feature = "group")]
1551impl GroupEncoding for SubgroupPoint {
1552    type Repr = <EdwardsPoint as GroupEncoding>::Repr;
1553
1554    fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
1555        EdwardsPoint::from_bytes(bytes).and_then(|p| p.into_subgroup())
1556    }
1557
1558    fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
1559        EdwardsPoint::from_bytes_unchecked(bytes).and_then(|p| p.into_subgroup())
1560    }
1561
1562    fn to_bytes(&self) -> Self::Repr {
1563        self.0.compress().to_bytes()
1564    }
1565}
1566
1567#[cfg(feature = "group")]
1568impl PrimeGroup for SubgroupPoint {}
1569
1570/// Ristretto has a cofactor of 1.
1571#[cfg(feature = "group")]
1572impl CofactorGroup for EdwardsPoint {
1573    type Subgroup = SubgroupPoint;
1574
1575    fn clear_cofactor(&self) -> Self::Subgroup {
1576        SubgroupPoint(self.mul_by_cofactor())
1577    }
1578
1579    fn into_subgroup(self) -> CtOption<Self::Subgroup> {
1580        CtOption::new(SubgroupPoint(self), CofactorGroup::is_torsion_free(&self))
1581    }
1582
1583    fn is_torsion_free(&self) -> Choice {
1584        (self * constants::BASEPOINT_ORDER_PRIVATE).ct_eq(&Self::identity())
1585    }
1586}
1587
1588// ------------------------------------------------------------------------
1589// Tests
1590// ------------------------------------------------------------------------
1591
1592#[cfg(test)]
1593mod test {
1594    use super::*;
1595
1596    // If `group` is set, then this is already imported in super
1597    #[cfg(not(feature = "group"))]
1598    use rand_core::RngCore;
1599
1600    #[cfg(feature = "alloc")]
1601    use alloc::vec::Vec;
1602
1603    #[cfg(feature = "precomputed-tables")]
1604    use crate::constants::ED25519_BASEPOINT_TABLE;
1605
1606    /// X coordinate of the basepoint.
1607    /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202
1608    static BASE_X_COORD_BYTES: [u8; 32] = [
1609        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c,
1610        0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36,
1611        0x69, 0x21,
1612    ];
1613
1614    /// Compressed Edwards Y form of 2*basepoint.
1615    static BASE2_CMPRSSD: CompressedEdwardsY = CompressedEdwardsY([
1616        0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0xe, 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39,
1617        0x97, 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd,
1618        0x60, 0x22,
1619    ]);
1620
1621    /// Compressed Edwards Y form of 16*basepoint.
1622    static BASE16_CMPRSSD: CompressedEdwardsY = CompressedEdwardsY([
1623        0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a,
1624        0xb0, 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96,
1625        0x96, 0x70,
1626    ]);
1627
1628    /// 4493907448824000747700850167940867464579944529806937181821189941592931634714
1629    pub static A_SCALAR: Scalar = Scalar {
1630        bytes: [
1631            0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8,
1632            0x26, 0x4d, 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, 0x58, 0x9e, 0x7b, 0x7f,
1633            0x23, 0x76, 0xef, 0x09,
1634        ],
1635    };
1636
1637    /// 2506056684125797857694181776241676200180934651973138769173342316833279714961
1638    pub static B_SCALAR: Scalar = Scalar {
1639        bytes: [
1640            0x91, 0x26, 0x7a, 0xcf, 0x25, 0xc2, 0x09, 0x1b, 0xa2, 0x17, 0x74, 0x7b, 0x66, 0xf0,
1641            0xb3, 0x2e, 0x9d, 0xf2, 0xa5, 0x67, 0x41, 0xcf, 0xda, 0xc4, 0x56, 0xa7, 0xd4, 0xaa,
1642            0xb8, 0x60, 0x8a, 0x05,
1643        ],
1644    };
1645
1646    /// A_SCALAR * basepoint, computed with ed25519.py
1647    pub static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([
1648        0xea, 0x27, 0xe2, 0x60, 0x53, 0xdf, 0x1b, 0x59, 0x56, 0xf1, 0x4d, 0x5d, 0xec, 0x3c, 0x34,
1649        0xc3, 0x84, 0xa2, 0x69, 0xb7, 0x4c, 0xc3, 0x80, 0x3e, 0xa8, 0xe2, 0xe7, 0xc9, 0x42, 0x5e,
1650        0x40, 0xa5,
1651    ]);
1652
1653    /// A_SCALAR * (A_TIMES_BASEPOINT) + B_SCALAR * BASEPOINT
1654    /// computed with ed25519.py
1655    static DOUBLE_SCALAR_MULT_RESULT: CompressedEdwardsY = CompressedEdwardsY([
1656        0x7d, 0xfd, 0x6c, 0x45, 0xaf, 0x6d, 0x6e, 0x0e, 0xba, 0x20, 0x37, 0x1a, 0x23, 0x64, 0x59,
1657        0xc4, 0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85, 0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13,
1658        0x2b, 0x42,
1659    ]);
1660
1661    /// Test round-trip decompression for the basepoint.
1662    #[test]
1663    fn basepoint_decompression_compression() {
1664        let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES);
1665        let bp = constants::ED25519_BASEPOINT_COMPRESSED
1666            .decompress()
1667            .unwrap();
1668        assert!(bp.is_valid());
1669        // Check that decompression actually gives the correct X coordinate
1670        assert_eq!(base_X, bp.X);
1671        assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED);
1672    }
1673
1674    /// Test sign handling in decompression
1675    #[test]
1676    fn decompression_sign_handling() {
1677        // Manually set the high bit of the last byte to flip the sign
1678        let mut minus_basepoint_bytes = *constants::ED25519_BASEPOINT_COMPRESSED.as_bytes();
1679        minus_basepoint_bytes[31] |= 1 << 7;
1680        let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes)
1681            .decompress()
1682            .unwrap();
1683        // Test projective coordinates exactly since we know they should
1684        // only differ by a flipped sign.
1685        assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT_POINT.X));
1686        assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT_POINT.Y);
1687        assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT_POINT.Z);
1688        assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT_POINT.T));
1689    }
1690
1691    /// Test that computing 1*basepoint gives the correct basepoint.
1692    #[cfg(feature = "precomputed-tables")]
1693    #[test]
1694    fn basepoint_mult_one_vs_basepoint() {
1695        let bp = ED25519_BASEPOINT_TABLE * &Scalar::ONE;
1696        let compressed = bp.compress();
1697        assert_eq!(compressed, constants::ED25519_BASEPOINT_COMPRESSED);
1698    }
1699
1700    /// Test that `EdwardsBasepointTable::basepoint()` gives the correct basepoint.
1701    #[cfg(feature = "precomputed-tables")]
1702    #[test]
1703    fn basepoint_table_basepoint_function_correct() {
1704        let bp = ED25519_BASEPOINT_TABLE.basepoint();
1705        assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED);
1706    }
1707
1708    /// Test `impl Add<EdwardsPoint> for EdwardsPoint`
1709    /// using basepoint + basepoint versus the 2*basepoint constant.
1710    #[test]
1711    fn basepoint_plus_basepoint_vs_basepoint2() {
1712        let bp = constants::ED25519_BASEPOINT_POINT;
1713        let bp_added = bp + bp;
1714        assert_eq!(bp_added.compress(), BASE2_CMPRSSD);
1715    }
1716
1717    /// Test `impl Add<ProjectiveNielsPoint> for EdwardsPoint`
1718    /// using the basepoint, basepoint2 constants
1719    #[test]
1720    fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() {
1721        let bp = constants::ED25519_BASEPOINT_POINT;
1722        let bp_added = (&bp + &bp.as_projective_niels()).as_extended();
1723        assert_eq!(bp_added.compress(), BASE2_CMPRSSD);
1724    }
1725
1726    /// Test `impl Add<AffineNielsPoint> for EdwardsPoint`
1727    /// using the basepoint, basepoint2 constants
1728    #[test]
1729    fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() {
1730        let bp = constants::ED25519_BASEPOINT_POINT;
1731        let bp_affine_niels = bp.as_affine_niels();
1732        let bp_added = (&bp + &bp_affine_niels).as_extended();
1733        assert_eq!(bp_added.compress(), BASE2_CMPRSSD);
1734    }
1735
1736    /// Check that equality of `EdwardsPoints` handles projective
1737    /// coordinates correctly.
1738    #[test]
1739    fn extended_point_equality_handles_scaling() {
1740        let mut two_bytes = [0u8; 32];
1741        two_bytes[0] = 2;
1742        let id1 = EdwardsPoint::identity();
1743        let id2 = EdwardsPoint {
1744            X: FieldElement::ZERO,
1745            Y: FieldElement::from_bytes(&two_bytes),
1746            Z: FieldElement::from_bytes(&two_bytes),
1747            T: FieldElement::ZERO,
1748        };
1749        assert!(bool::from(id1.ct_eq(&id2)));
1750    }
1751
1752    /// Sanity check for conversion to precomputed points
1753    #[cfg(feature = "precomputed-tables")]
1754    #[test]
1755    fn to_affine_niels_clears_denominators() {
1756        // construct a point as aB so it has denominators (ie. Z != 1)
1757        let aB = ED25519_BASEPOINT_TABLE * &A_SCALAR;
1758        let aB_affine_niels = aB.as_affine_niels();
1759        let also_aB = (&EdwardsPoint::identity() + &aB_affine_niels).as_extended();
1760        assert_eq!(aB.compress(), also_aB.compress());
1761    }
1762
1763    /// Test mul_base versus a known scalar multiple from ed25519.py
1764    #[test]
1765    fn basepoint_mult_vs_ed25519py() {
1766        let aB = EdwardsPoint::mul_base(&A_SCALAR);
1767        assert_eq!(aB.compress(), A_TIMES_BASEPOINT);
1768    }
1769
1770    /// Test that multiplication by the basepoint order kills the basepoint
1771    #[test]
1772    fn basepoint_mult_by_basepoint_order() {
1773        let should_be_id = EdwardsPoint::mul_base(&constants::BASEPOINT_ORDER_PRIVATE);
1774        assert!(should_be_id.is_identity());
1775    }
1776
1777    /// Test precomputed basepoint mult
1778    #[cfg(feature = "precomputed-tables")]
1779    #[test]
1780    fn test_precomputed_basepoint_mult() {
1781        let aB_1 = ED25519_BASEPOINT_TABLE * &A_SCALAR;
1782        let aB_2 = constants::ED25519_BASEPOINT_POINT * A_SCALAR;
1783        assert_eq!(aB_1.compress(), aB_2.compress());
1784    }
1785
1786    /// Test scalar_mul versus a known scalar multiple from ed25519.py
1787    #[test]
1788    fn scalar_mul_vs_ed25519py() {
1789        let aB = constants::ED25519_BASEPOINT_POINT * A_SCALAR;
1790        assert_eq!(aB.compress(), A_TIMES_BASEPOINT);
1791    }
1792
1793    /// Test basepoint.double() versus the 2*basepoint constant.
1794    #[test]
1795    fn basepoint_double_vs_basepoint2() {
1796        assert_eq!(
1797            constants::ED25519_BASEPOINT_POINT.double().compress(),
1798            BASE2_CMPRSSD
1799        );
1800    }
1801
1802    /// Test that computing 2*basepoint is the same as basepoint.double()
1803    #[test]
1804    fn basepoint_mult_two_vs_basepoint2() {
1805        let two = Scalar::from(2u64);
1806        let bp2 = EdwardsPoint::mul_base(&two);
1807        assert_eq!(bp2.compress(), BASE2_CMPRSSD);
1808    }
1809
1810    /// Test that all the basepoint table types compute the same results.
1811    #[cfg(feature = "precomputed-tables")]
1812    #[test]
1813    fn basepoint_tables() {
1814        let P = &constants::ED25519_BASEPOINT_POINT;
1815        let a = A_SCALAR;
1816
1817        let table_radix16 = EdwardsBasepointTableRadix16::create(P);
1818        let table_radix32 = EdwardsBasepointTableRadix32::create(P);
1819        let table_radix64 = EdwardsBasepointTableRadix64::create(P);
1820        let table_radix128 = EdwardsBasepointTableRadix128::create(P);
1821        let table_radix256 = EdwardsBasepointTableRadix256::create(P);
1822
1823        let aP = (ED25519_BASEPOINT_TABLE * &a).compress();
1824        let aP16 = (&table_radix16 * &a).compress();
1825        let aP32 = (&table_radix32 * &a).compress();
1826        let aP64 = (&table_radix64 * &a).compress();
1827        let aP128 = (&table_radix128 * &a).compress();
1828        let aP256 = (&table_radix256 * &a).compress();
1829
1830        assert_eq!(aP, aP16);
1831        assert_eq!(aP16, aP32);
1832        assert_eq!(aP32, aP64);
1833        assert_eq!(aP64, aP128);
1834        assert_eq!(aP128, aP256);
1835    }
1836
1837    /// Check unreduced scalar multiplication by the basepoint tables is the same no matter what
1838    /// radix the table is.
1839    #[cfg(feature = "precomputed-tables")]
1840    #[test]
1841    fn basepoint_tables_unreduced_scalar() {
1842        let P = &constants::ED25519_BASEPOINT_POINT;
1843        let a = crate::scalar::test::LARGEST_UNREDUCED_SCALAR;
1844
1845        let table_radix16 = EdwardsBasepointTableRadix16::create(P);
1846        let table_radix32 = EdwardsBasepointTableRadix32::create(P);
1847        let table_radix64 = EdwardsBasepointTableRadix64::create(P);
1848        let table_radix128 = EdwardsBasepointTableRadix128::create(P);
1849        let table_radix256 = EdwardsBasepointTableRadix256::create(P);
1850
1851        let aP = (ED25519_BASEPOINT_TABLE * &a).compress();
1852        let aP16 = (&table_radix16 * &a).compress();
1853        let aP32 = (&table_radix32 * &a).compress();
1854        let aP64 = (&table_radix64 * &a).compress();
1855        let aP128 = (&table_radix128 * &a).compress();
1856        let aP256 = (&table_radix256 * &a).compress();
1857
1858        assert_eq!(aP, aP16);
1859        assert_eq!(aP16, aP32);
1860        assert_eq!(aP32, aP64);
1861        assert_eq!(aP64, aP128);
1862        assert_eq!(aP128, aP256);
1863    }
1864
1865    /// Check that converting to projective and then back to extended round-trips.
1866    #[test]
1867    fn basepoint_projective_extended_round_trip() {
1868        assert_eq!(
1869            constants::ED25519_BASEPOINT_POINT
1870                .as_projective()
1871                .as_extended()
1872                .compress(),
1873            constants::ED25519_BASEPOINT_COMPRESSED
1874        );
1875    }
1876
1877    /// Test computing 16*basepoint vs mul_by_pow_2(4)
1878    #[test]
1879    fn basepoint16_vs_mul_by_pow_2_4() {
1880        let bp16 = constants::ED25519_BASEPOINT_POINT.mul_by_pow_2(4);
1881        assert_eq!(bp16.compress(), BASE16_CMPRSSD);
1882    }
1883
1884    /// Check that mul_base_clamped and mul_clamped agree
1885    #[test]
1886    fn mul_base_clamped() {
1887        let mut csprng = rand_core::OsRng;
1888
1889        // Make a random curve point in the curve. Give it torsion to make things interesting.
1890        #[cfg(feature = "precomputed-tables")]
1891        let random_point = {
1892            let mut b = [0u8; 32];
1893            csprng.fill_bytes(&mut b);
1894            EdwardsPoint::mul_base_clamped(b) + constants::EIGHT_TORSION[1]
1895        };
1896        // Make a basepoint table from the random point. We'll use this with mul_base_clamped
1897        #[cfg(feature = "precomputed-tables")]
1898        let random_table = EdwardsBasepointTableRadix256::create(&random_point);
1899
1900        // Now test scalar mult. agreement on the default basepoint as well as random_point
1901
1902        // Test that mul_base_clamped and mul_clamped agree on a large integer. Even after
1903        // clamping, this integer is not reduced mod l.
1904        let a_bytes = [0xff; 32];
1905        assert_eq!(
1906            EdwardsPoint::mul_base_clamped(a_bytes),
1907            constants::ED25519_BASEPOINT_POINT.mul_clamped(a_bytes)
1908        );
1909        #[cfg(feature = "precomputed-tables")]
1910        assert_eq!(
1911            random_table.mul_base_clamped(a_bytes),
1912            random_point.mul_clamped(a_bytes)
1913        );
1914
1915        // Test agreement on random integers
1916        for _ in 0..100 {
1917            // This will be reduced mod l with probability l / 2^256 ≈ 6.25%
1918            let mut a_bytes = [0u8; 32];
1919            csprng.fill_bytes(&mut a_bytes);
1920
1921            assert_eq!(
1922                EdwardsPoint::mul_base_clamped(a_bytes),
1923                constants::ED25519_BASEPOINT_POINT.mul_clamped(a_bytes)
1924            );
1925            #[cfg(feature = "precomputed-tables")]
1926            assert_eq!(
1927                random_table.mul_base_clamped(a_bytes),
1928                random_point.mul_clamped(a_bytes)
1929            );
1930        }
1931    }
1932
1933    #[test]
1934    #[cfg(feature = "alloc")]
1935    fn impl_sum() {
1936        // Test that sum works for non-empty iterators
1937        let BASE = constants::ED25519_BASEPOINT_POINT;
1938
1939        let s1 = Scalar::from(999u64);
1940        let P1 = BASE * s1;
1941
1942        let s2 = Scalar::from(333u64);
1943        let P2 = BASE * s2;
1944
1945        let vec = vec![P1, P2];
1946        let sum: EdwardsPoint = vec.iter().sum();
1947
1948        assert_eq!(sum, P1 + P2);
1949
1950        // Test that sum works for the empty iterator
1951        let empty_vector: Vec<EdwardsPoint> = vec![];
1952        let sum: EdwardsPoint = empty_vector.iter().sum();
1953
1954        assert_eq!(sum, EdwardsPoint::identity());
1955
1956        // Test that sum works on owning iterators
1957        let s = Scalar::from(2u64);
1958        let mapped = vec.iter().map(|x| x * s);
1959        let sum: EdwardsPoint = mapped.sum();
1960
1961        assert_eq!(sum, P1 * s + P2 * s);
1962    }
1963
1964    /// Test that the conditional assignment trait works for AffineNielsPoints.
1965    #[test]
1966    fn conditional_assign_for_affine_niels_point() {
1967        let id = AffineNielsPoint::identity();
1968        let mut p1 = AffineNielsPoint::identity();
1969        let bp = constants::ED25519_BASEPOINT_POINT.as_affine_niels();
1970
1971        p1.conditional_assign(&bp, Choice::from(0));
1972        assert_eq!(p1, id);
1973        p1.conditional_assign(&bp, Choice::from(1));
1974        assert_eq!(p1, bp);
1975    }
1976
1977    #[test]
1978    fn is_small_order() {
1979        // The basepoint has large prime order
1980        assert!(!constants::ED25519_BASEPOINT_POINT.is_small_order());
1981        // constants::EIGHT_TORSION has all points of small order.
1982        for torsion_point in &constants::EIGHT_TORSION {
1983            assert!(torsion_point.is_small_order());
1984        }
1985    }
1986
1987    #[test]
1988    fn compressed_identity() {
1989        assert_eq!(
1990            EdwardsPoint::identity().compress(),
1991            CompressedEdwardsY::identity()
1992        );
1993    }
1994
1995    #[test]
1996    fn is_identity() {
1997        assert!(EdwardsPoint::identity().is_identity());
1998        assert!(!constants::ED25519_BASEPOINT_POINT.is_identity());
1999    }
2000
2001    /// Rust's debug builds have overflow and underflow trapping,
2002    /// and enable `debug_assert!()`.  This performs many scalar
2003    /// multiplications to attempt to trigger possible overflows etc.
2004    ///
2005    /// For instance, the `u64` `Mul` implementation for
2006    /// `FieldElements` requires the input `Limb`s to be bounded by
2007    /// 2^54, but we cannot enforce this dynamically at runtime, or
2008    /// statically at compile time (until Rust gets type-level
2009    /// integers, at which point we can encode "bits of headroom" into
2010    /// the type system and prove correctness).
2011    #[test]
2012    fn monte_carlo_overflow_underflow_debug_assert_test() {
2013        let mut P = constants::ED25519_BASEPOINT_POINT;
2014        // N.B. each scalar_mul does 1407 field mults, 1024 field squarings,
2015        // so this does ~ 1M of each operation.
2016        for _ in 0..1_000 {
2017            P *= &A_SCALAR;
2018        }
2019    }
2020
2021    #[test]
2022    fn scalarmult_extended_point_works_both_ways() {
2023        let G: EdwardsPoint = constants::ED25519_BASEPOINT_POINT;
2024        let s: Scalar = A_SCALAR;
2025
2026        let P1 = G * s;
2027        let P2 = s * G;
2028
2029        assert!(P1.compress().to_bytes() == P2.compress().to_bytes());
2030    }
2031
2032    // A single iteration of a consistency check for MSM.
2033    #[cfg(feature = "alloc")]
2034    fn multiscalar_consistency_iter(n: usize) {
2035        let mut rng = rand::thread_rng();
2036
2037        // Construct random coefficients x0, ..., x_{n-1},
2038        // followed by some extra hardcoded ones.
2039        let xs = (0..n).map(|_| Scalar::random(&mut rng)).collect::<Vec<_>>();
2040        let check = xs.iter().map(|xi| xi * xi).sum::<Scalar>();
2041
2042        // Construct points G_i = x_i * B
2043        let Gs = xs.iter().map(EdwardsPoint::mul_base).collect::<Vec<_>>();
2044
2045        // Compute H1 = <xs, Gs> (consttime)
2046        let H1 = EdwardsPoint::multiscalar_mul(&xs, &Gs);
2047        // Compute H2 = <xs, Gs> (vartime)
2048        let H2 = EdwardsPoint::vartime_multiscalar_mul(&xs, &Gs);
2049        // Compute H3 = <xs, Gs> = sum(xi^2) * B
2050        let H3 = EdwardsPoint::mul_base(&check);
2051
2052        assert_eq!(H1, H3);
2053        assert_eq!(H2, H3);
2054    }
2055
2056    // Use different multiscalar sizes to hit different internal
2057    // parameters.
2058
2059    #[test]
2060    #[cfg(feature = "alloc")]
2061    fn multiscalar_consistency_n_100() {
2062        let iters = 50;
2063        for _ in 0..iters {
2064            multiscalar_consistency_iter(100);
2065        }
2066    }
2067
2068    #[test]
2069    #[cfg(feature = "alloc")]
2070    fn multiscalar_consistency_n_250() {
2071        let iters = 50;
2072        for _ in 0..iters {
2073            multiscalar_consistency_iter(250);
2074        }
2075    }
2076
2077    #[test]
2078    #[cfg(feature = "alloc")]
2079    fn multiscalar_consistency_n_500() {
2080        let iters = 50;
2081        for _ in 0..iters {
2082            multiscalar_consistency_iter(500);
2083        }
2084    }
2085
2086    #[test]
2087    #[cfg(feature = "alloc")]
2088    fn multiscalar_consistency_n_1000() {
2089        let iters = 50;
2090        for _ in 0..iters {
2091            multiscalar_consistency_iter(1000);
2092        }
2093    }
2094
2095    #[test]
2096    #[cfg(feature = "alloc")]
2097    fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
2098        let mut rng = rand::thread_rng();
2099
2100        let static_scalars = (0..128)
2101            .map(|_| Scalar::random(&mut rng))
2102            .collect::<Vec<_>>();
2103
2104        let dynamic_scalars = (0..128)
2105            .map(|_| Scalar::random(&mut rng))
2106            .collect::<Vec<_>>();
2107
2108        let check_scalar: Scalar = static_scalars
2109            .iter()
2110            .chain(dynamic_scalars.iter())
2111            .map(|s| s * s)
2112            .sum();
2113
2114        let static_points = static_scalars
2115            .iter()
2116            .map(EdwardsPoint::mul_base)
2117            .collect::<Vec<_>>();
2118        let dynamic_points = dynamic_scalars
2119            .iter()
2120            .map(EdwardsPoint::mul_base)
2121            .collect::<Vec<_>>();
2122
2123        let precomputation = VartimeEdwardsPrecomputation::new(static_points.iter());
2124
2125        let P = precomputation.vartime_mixed_multiscalar_mul(
2126            &static_scalars,
2127            &dynamic_scalars,
2128            &dynamic_points,
2129        );
2130
2131        use crate::traits::VartimeMultiscalarMul;
2132        let Q = EdwardsPoint::vartime_multiscalar_mul(
2133            static_scalars.iter().chain(dynamic_scalars.iter()),
2134            static_points.iter().chain(dynamic_points.iter()),
2135        );
2136
2137        let R = EdwardsPoint::mul_base(&check_scalar);
2138
2139        assert_eq!(P.compress(), R.compress());
2140        assert_eq!(Q.compress(), R.compress());
2141    }
2142
2143    mod vartime {
2144        use super::super::*;
2145        use super::{A_SCALAR, A_TIMES_BASEPOINT, B_SCALAR, DOUBLE_SCALAR_MULT_RESULT};
2146
2147        /// Test double_scalar_mul_vartime vs ed25519.py
2148        #[test]
2149        fn double_scalar_mul_basepoint_vs_ed25519py() {
2150            let A = A_TIMES_BASEPOINT.decompress().unwrap();
2151            let result =
2152                EdwardsPoint::vartime_double_scalar_mul_basepoint(&A_SCALAR, &A, &B_SCALAR);
2153            assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT);
2154        }
2155
2156        #[test]
2157        #[cfg(feature = "alloc")]
2158        fn multiscalar_mul_vs_ed25519py() {
2159            let A = A_TIMES_BASEPOINT.decompress().unwrap();
2160            let result = EdwardsPoint::vartime_multiscalar_mul(
2161                &[A_SCALAR, B_SCALAR],
2162                &[A, constants::ED25519_BASEPOINT_POINT],
2163            );
2164            assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT);
2165        }
2166
2167        #[test]
2168        #[cfg(feature = "alloc")]
2169        fn multiscalar_mul_vartime_vs_consttime() {
2170            let A = A_TIMES_BASEPOINT.decompress().unwrap();
2171            let result_vartime = EdwardsPoint::vartime_multiscalar_mul(
2172                &[A_SCALAR, B_SCALAR],
2173                &[A, constants::ED25519_BASEPOINT_POINT],
2174            );
2175            let result_consttime = EdwardsPoint::multiscalar_mul(
2176                &[A_SCALAR, B_SCALAR],
2177                &[A, constants::ED25519_BASEPOINT_POINT],
2178            );
2179
2180            assert_eq!(result_vartime.compress(), result_consttime.compress());
2181        }
2182    }
2183
2184    #[test]
2185    #[cfg(feature = "serde")]
2186    fn serde_bincode_basepoint_roundtrip() {
2187        use bincode;
2188
2189        let encoded = bincode::serialize(&constants::ED25519_BASEPOINT_POINT).unwrap();
2190        let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap();
2191        assert_eq!(encoded, enc_compressed);
2192
2193        // Check that the encoding is 32 bytes exactly
2194        assert_eq!(encoded.len(), 32);
2195
2196        let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap();
2197        let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap();
2198
2199        assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT);
2200        assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED);
2201
2202        // Check that the encoding itself matches the usual one
2203        let raw_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes();
2204        let bp: EdwardsPoint = bincode::deserialize(raw_bytes).unwrap();
2205        assert_eq!(bp, constants::ED25519_BASEPOINT_POINT);
2206    }
2207
2208    ////////////////////////////////////////////////////////////
2209    // Signal tests from                                      //
2210    //     https://github.com/signalapp/libsignal-protocol-c/ //
2211    ////////////////////////////////////////////////////////////
2212
2213    #[cfg(all(feature = "alloc", feature = "digest"))]
2214    fn test_vectors() -> Vec<Vec<&'static str>> {
2215        vec![
2216            vec![
2217                "214f306e1576f5a7577636fe303ca2c625b533319f52442b22a9fa3b7ede809f",
2218                "c95becf0f93595174633b9d4d6bbbeb88e16fa257176f877ce426e1424626052",
2219            ],
2220            vec![
2221                "2eb10d432702ea7f79207da95d206f82d5a3b374f5f89f17a199531f78d3bea6",
2222                "d8f8b508edffbb8b6dab0f602f86a9dd759f800fe18f782fdcac47c234883e7f",
2223            ],
2224            vec![
2225                "84cbe9accdd32b46f4a8ef51c85fd39d028711f77fb00e204a613fc235fd68b9",
2226                "93c73e0289afd1d1fc9e4e78a505d5d1b2642fbdf91a1eff7d281930654b1453",
2227            ],
2228            vec![
2229                "c85165952490dc1839cb69012a3d9f2cc4b02343613263ab93a26dc89fd58267",
2230                "43cbe8685fd3c90665b91835debb89ff1477f906f5170f38a192f6a199556537",
2231            ],
2232            vec![
2233                "26e7fc4a78d863b1a4ccb2ce0951fbcd021e106350730ee4157bacb4502e1b76",
2234                "b6fc3d738c2c40719479b2f23818180cdafa72a14254d4016bbed8f0b788a835",
2235            ],
2236            vec![
2237                "1618c08ef0233f94f0f163f9435ec7457cd7a8cd4bb6b160315d15818c30f7a2",
2238                "da0b703593b29dbcd28ebd6e7baea17b6f61971f3641cae774f6a5137a12294c",
2239            ],
2240            vec![
2241                "48b73039db6fcdcb6030c4a38e8be80b6390d8ae46890e77e623f87254ef149c",
2242                "ca11b25acbc80566603eabeb9364ebd50e0306424c61049e1ce9385d9f349966",
2243            ],
2244            vec![
2245                "a744d582b3a34d14d311b7629da06d003045ae77cebceeb4e0e72734d63bd07d",
2246                "fad25a5ea15d4541258af8785acaf697a886c1b872c793790e60a6837b1adbc0",
2247            ],
2248            vec![
2249                "80a6ff33494c471c5eff7efb9febfbcf30a946fe6535b3451cda79f2154a7095",
2250                "57ac03913309b3f8cd3c3d4c49d878bb21f4d97dc74a1eaccbe5c601f7f06f47",
2251            ],
2252            vec![
2253                "f06fc939bc10551a0fd415aebf107ef0b9c4ee1ef9a164157bdd089127782617",
2254                "785b2a6a00a5579cc9da1ff997ce8339b6f9fb46c6f10cf7a12ff2986341a6e0",
2255            ],
2256        ]
2257    }
2258
2259    #[test]
2260    #[allow(deprecated)]
2261    #[cfg(all(feature = "alloc", feature = "digest"))]
2262    fn elligator_signal_test_vectors() {
2263        for vector in test_vectors().iter() {
2264            let input = hex::decode(vector[0]).unwrap();
2265            let output = hex::decode(vector[1]).unwrap();
2266
2267            let point = EdwardsPoint::nonspec_map_to_curve::<sha2::Sha512>(&input);
2268            assert_eq!(point.compress().to_bytes(), output[..]);
2269        }
2270    }
2271}