2017-11-17 01:34:28 +00:00
|
|
|
// -*- mode: rust; -*-
|
|
|
|
|
//
|
|
|
|
|
// This file is part of curve25519-dalek.
|
2021-03-25 04:10:55 +00:00
|
|
|
// Copyright (c) 2016-2021 isis lovecruft
|
|
|
|
|
// Copyright (c) 2016-2019 Henry de Valence
|
2017-11-17 01:34:28 +00:00
|
|
|
// See LICENSE for licensing information.
|
|
|
|
|
//
|
|
|
|
|
// Authors:
|
2021-03-25 04:10:55 +00:00
|
|
|
// - isis agora lovecruft <isis@patternsinthevoid.net>
|
2017-11-17 01:34:28 +00:00
|
|
|
// - Henry de Valence <hdevalence@hdevalence.ca>
|
|
|
|
|
|
|
|
|
|
//! Module for common traits.
|
|
|
|
|
|
2019-05-26 11:00:07 +00:00
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
|
2018-05-02 21:54:46 +00:00
|
|
|
use core::borrow::Borrow;
|
|
|
|
|
|
2023-03-28 22:12:24 +00:00
|
|
|
use crate::scalar::{clamp_integer, Scalar};
|
2024-03-01 01:56:52 +00:00
|
|
|
use subtle::ConstantTimeEq;
|
2018-05-02 21:54:46 +00:00
|
|
|
|
2017-11-17 01:34:28 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
// Public Traits
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/// Trait for getting the identity element of a point type.
|
|
|
|
|
pub trait Identity {
|
|
|
|
|
/// Returns the identity element of the curve.
|
|
|
|
|
/// Can be used as a constructor.
|
|
|
|
|
fn identity() -> Self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Trait for testing if a curve point is equivalent to the identity point.
|
|
|
|
|
pub trait IsIdentity {
|
|
|
|
|
/// Return true if this element is the identity element of the curve.
|
|
|
|
|
fn is_identity(&self) -> bool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Implement generic identity equality testing for a point representations
|
|
|
|
|
/// which have constant-time equality testing and a defined identity
|
|
|
|
|
/// constructor.
|
2018-05-02 21:54:46 +00:00
|
|
|
impl<T> IsIdentity for T
|
|
|
|
|
where
|
2024-03-01 01:56:52 +00:00
|
|
|
T: ConstantTimeEq + Identity,
|
2018-05-02 21:54:46 +00:00
|
|
|
{
|
2017-11-17 01:34:28 +00:00
|
|
|
fn is_identity(&self) -> bool {
|
2023-05-31 01:49:13 +00:00
|
|
|
self.ct_eq(&T::identity()).into()
|
2017-11-17 01:34:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-27 12:54:52 +00:00
|
|
|
/// A precomputed table of basepoints, for optimising scalar multiplications.
|
|
|
|
|
pub trait BasepointTable {
|
|
|
|
|
/// The type of point contained within this table.
|
|
|
|
|
type Point;
|
|
|
|
|
|
|
|
|
|
/// Generate a new precomputed basepoint table from the given basepoint.
|
|
|
|
|
fn create(basepoint: &Self::Point) -> Self;
|
|
|
|
|
|
|
|
|
|
/// Retrieve the original basepoint from this table.
|
|
|
|
|
fn basepoint(&self) -> Self::Point;
|
|
|
|
|
|
|
|
|
|
/// Multiply a `scalar` by this precomputed basepoint table, in constant time.
|
2023-01-08 08:51:51 +00:00
|
|
|
fn mul_base(&self, scalar: &Scalar) -> Self::Point;
|
2023-03-28 22:12:24 +00:00
|
|
|
|
|
|
|
|
/// Multiply `clamp_integer(bytes)` by this precomputed basepoint table, in constant time. For
|
|
|
|
|
/// a description of clamping, see [`clamp_integer`].
|
|
|
|
|
fn mul_base_clamped(&self, bytes: [u8; 32]) -> Self::Point {
|
|
|
|
|
// Basepoint multiplication is defined for all values of `bytes` up to and including
|
|
|
|
|
// 2^255 - 1. The limit comes from the fact that scalar.as_radix_16() doesn't work for
|
|
|
|
|
// most scalars larger than 2^255.
|
|
|
|
|
let s = Scalar {
|
|
|
|
|
bytes: clamp_integer(bytes),
|
|
|
|
|
};
|
|
|
|
|
self.mul_base(&s)
|
|
|
|
|
}
|
2019-12-27 12:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
2018-05-02 21:54:46 +00:00
|
|
|
/// A trait for constant-time multiscalar multiplication without precomputation.
|
|
|
|
|
pub trait MultiscalarMul {
|
|
|
|
|
/// The type of point being multiplied, e.g., `RistrettoPoint`.
|
|
|
|
|
type Point;
|
|
|
|
|
|
|
|
|
|
/// Given an iterator of (possibly secret) scalars and an iterator of
|
|
|
|
|
/// public points, compute
|
|
|
|
|
/// $$
|
|
|
|
|
/// Q = c\_1 P\_1 + \cdots + c\_n P\_n.
|
|
|
|
|
/// $$
|
|
|
|
|
///
|
|
|
|
|
/// It is an error to call this function with two iterators of different lengths.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// The trait bound aims for maximum flexibility: the inputs must be
|
2025-06-04 15:40:10 +00:00
|
|
|
/// convertible to iterators (`I: IntoIter`), and the iterator's items
|
2018-05-02 21:54:46 +00:00
|
|
|
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
|
|
|
|
|
/// iterators returning either `Scalar`s or `&Scalar`s.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2022-11-14 05:11:23 +00:00
|
|
|
/// # #[cfg(feature = "alloc")]
|
|
|
|
|
/// # {
|
2018-05-02 21:54:46 +00:00
|
|
|
/// use curve25519_dalek::constants;
|
|
|
|
|
/// use curve25519_dalek::traits::MultiscalarMul;
|
|
|
|
|
/// use curve25519_dalek::ristretto::RistrettoPoint;
|
|
|
|
|
/// use curve25519_dalek::scalar::Scalar;
|
|
|
|
|
///
|
|
|
|
|
/// // Some scalars
|
2018-07-17 17:53:02 +00:00
|
|
|
/// let a = Scalar::from(87329482u64);
|
|
|
|
|
/// let b = Scalar::from(37264829u64);
|
|
|
|
|
/// let c = Scalar::from(98098098u64);
|
2018-05-02 21:54:46 +00:00
|
|
|
///
|
|
|
|
|
/// // Some points
|
|
|
|
|
/// let P = constants::RISTRETTO_BASEPOINT_POINT;
|
|
|
|
|
/// let Q = P + P;
|
|
|
|
|
/// let R = P + Q;
|
|
|
|
|
///
|
|
|
|
|
/// // A1 = a*P + b*Q + c*R
|
|
|
|
|
/// let abc = [a,b,c];
|
|
|
|
|
/// let A1 = RistrettoPoint::multiscalar_mul(&abc, &[P,Q,R]);
|
|
|
|
|
/// // Note: (&abc).into_iter(): Iterator<Item=&Scalar>
|
|
|
|
|
///
|
|
|
|
|
/// // A2 = (-a)*P + (-b)*Q + (-c)*R
|
|
|
|
|
/// let minus_abc = abc.iter().map(|x| -x);
|
|
|
|
|
/// let A2 = RistrettoPoint::multiscalar_mul(minus_abc, &[P,Q,R]);
|
|
|
|
|
/// // Note: minus_abc.into_iter(): Iterator<Item=Scalar>
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(A1.compress(), (-A2).compress());
|
2022-11-14 05:11:23 +00:00
|
|
|
/// # }
|
2018-05-02 21:54:46 +00:00
|
|
|
/// ```
|
|
|
|
|
fn multiscalar_mul<I, J>(scalars: I, points: J) -> Self::Point
|
|
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Scalar>,
|
|
|
|
|
J: IntoIterator,
|
|
|
|
|
J::Item: Borrow<Self::Point>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A trait for variable-time multiscalar multiplication without precomputation.
|
|
|
|
|
pub trait VartimeMultiscalarMul {
|
|
|
|
|
/// The type of point being multiplied, e.g., `RistrettoPoint`.
|
|
|
|
|
type Point;
|
|
|
|
|
|
2018-07-17 15:19:48 +00:00
|
|
|
/// Given an iterator of public scalars and an iterator of
|
|
|
|
|
/// `Option`s of points, compute either `Some(Q)`, where
|
|
|
|
|
/// $$
|
|
|
|
|
/// Q = c\_1 P\_1 + \cdots + c\_n P\_n,
|
|
|
|
|
/// $$
|
|
|
|
|
/// if all points were `Some(P_i)`, or else return `None`.
|
|
|
|
|
///
|
|
|
|
|
/// This function is particularly useful when verifying statements
|
|
|
|
|
/// involving compressed points. Accepting `Option<Point>` allows
|
|
|
|
|
/// inlining point decompression into the multiscalar call,
|
|
|
|
|
/// avoiding the need for temporary buffers.
|
|
|
|
|
/// ```
|
2022-11-14 05:11:23 +00:00
|
|
|
/// #[cfg(feature = "alloc")]
|
|
|
|
|
/// # {
|
2018-07-17 15:19:48 +00:00
|
|
|
/// use curve25519_dalek::constants;
|
|
|
|
|
/// use curve25519_dalek::traits::VartimeMultiscalarMul;
|
|
|
|
|
/// use curve25519_dalek::ristretto::RistrettoPoint;
|
|
|
|
|
/// use curve25519_dalek::scalar::Scalar;
|
|
|
|
|
///
|
|
|
|
|
/// // Some scalars
|
2018-07-20 18:50:42 +00:00
|
|
|
/// let a = Scalar::from(87329482u64);
|
|
|
|
|
/// let b = Scalar::from(37264829u64);
|
|
|
|
|
/// let c = Scalar::from(98098098u64);
|
2018-07-17 15:19:48 +00:00
|
|
|
/// let abc = [a,b,c];
|
|
|
|
|
///
|
|
|
|
|
/// // Some points
|
|
|
|
|
/// let P = constants::RISTRETTO_BASEPOINT_POINT;
|
|
|
|
|
/// let Q = P + P;
|
|
|
|
|
/// let R = P + Q;
|
|
|
|
|
/// let PQR = [P, Q, R];
|
|
|
|
|
///
|
|
|
|
|
/// let compressed = [P.compress(), Q.compress(), R.compress()];
|
|
|
|
|
///
|
|
|
|
|
/// // Now we can compute A1 = a*P + b*Q + c*R using P, Q, R:
|
|
|
|
|
/// let A1 = RistrettoPoint::vartime_multiscalar_mul(&abc, &PQR);
|
|
|
|
|
///
|
|
|
|
|
/// // Or using the compressed points:
|
|
|
|
|
/// let A2 = RistrettoPoint::optional_multiscalar_mul(
|
|
|
|
|
/// &abc,
|
|
|
|
|
/// compressed.iter().map(|pt| pt.decompress()),
|
|
|
|
|
/// );
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(A2, Some(A1));
|
|
|
|
|
///
|
|
|
|
|
/// // It's also possible to mix compressed and uncompressed points:
|
|
|
|
|
/// let A3 = RistrettoPoint::optional_multiscalar_mul(
|
|
|
|
|
/// abc.iter()
|
|
|
|
|
/// .chain(abc.iter()),
|
|
|
|
|
/// compressed.iter().map(|pt| pt.decompress())
|
|
|
|
|
/// .chain(PQR.iter().map(|&pt| Some(pt))),
|
|
|
|
|
/// );
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(A3, Some(A1+A1));
|
2022-11-14 05:11:23 +00:00
|
|
|
/// # }
|
2018-07-17 15:19:48 +00:00
|
|
|
/// ```
|
|
|
|
|
fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<Self::Point>
|
|
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Scalar>,
|
|
|
|
|
J: IntoIterator<Item = Option<Self::Point>>;
|
|
|
|
|
|
2018-07-17 05:54:45 +00:00
|
|
|
/// Given an iterator of public scalars and an iterator of
|
2018-05-02 21:54:46 +00:00
|
|
|
/// public points, compute
|
|
|
|
|
/// $$
|
2018-07-17 05:54:45 +00:00
|
|
|
/// Q = c\_1 P\_1 + \cdots + c\_n P\_n,
|
2018-05-02 21:54:46 +00:00
|
|
|
/// $$
|
2018-07-17 05:54:45 +00:00
|
|
|
/// using variable-time operations.
|
2018-05-02 21:54:46 +00:00
|
|
|
///
|
|
|
|
|
/// It is an error to call this function with two iterators of different lengths.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// The trait bound aims for maximum flexibility: the inputs must be
|
2025-06-04 15:40:10 +00:00
|
|
|
/// convertible to iterators (`I: IntoIter`), and the iterator's items
|
2018-05-02 21:54:46 +00:00
|
|
|
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
|
|
|
|
|
/// iterators returning either `Scalar`s or `&Scalar`s.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2022-11-14 05:11:23 +00:00
|
|
|
/// #[cfg(feature = "alloc")]
|
|
|
|
|
/// # {
|
2018-05-02 21:54:46 +00:00
|
|
|
/// use curve25519_dalek::constants;
|
2018-07-17 05:54:45 +00:00
|
|
|
/// use curve25519_dalek::traits::VartimeMultiscalarMul;
|
2018-05-02 21:54:46 +00:00
|
|
|
/// use curve25519_dalek::ristretto::RistrettoPoint;
|
|
|
|
|
/// use curve25519_dalek::scalar::Scalar;
|
|
|
|
|
///
|
|
|
|
|
/// // Some scalars
|
2018-07-17 17:53:02 +00:00
|
|
|
/// let a = Scalar::from(87329482u64);
|
|
|
|
|
/// let b = Scalar::from(37264829u64);
|
|
|
|
|
/// let c = Scalar::from(98098098u64);
|
2018-05-02 21:54:46 +00:00
|
|
|
///
|
|
|
|
|
/// // Some points
|
|
|
|
|
/// let P = constants::RISTRETTO_BASEPOINT_POINT;
|
|
|
|
|
/// let Q = P + P;
|
|
|
|
|
/// let R = P + Q;
|
|
|
|
|
///
|
|
|
|
|
/// // A1 = a*P + b*Q + c*R
|
|
|
|
|
/// let abc = [a,b,c];
|
2018-07-17 05:54:45 +00:00
|
|
|
/// let A1 = RistrettoPoint::vartime_multiscalar_mul(&abc, &[P,Q,R]);
|
2018-05-02 21:54:46 +00:00
|
|
|
/// // Note: (&abc).into_iter(): Iterator<Item=&Scalar>
|
|
|
|
|
///
|
|
|
|
|
/// // A2 = (-a)*P + (-b)*Q + (-c)*R
|
|
|
|
|
/// let minus_abc = abc.iter().map(|x| -x);
|
2018-07-17 05:54:45 +00:00
|
|
|
/// let A2 = RistrettoPoint::vartime_multiscalar_mul(minus_abc, &[P,Q,R]);
|
2018-05-02 21:54:46 +00:00
|
|
|
/// // Note: minus_abc.into_iter(): Iterator<Item=Scalar>
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(A1.compress(), (-A2).compress());
|
2022-11-14 05:11:23 +00:00
|
|
|
/// # }
|
2018-05-02 21:54:46 +00:00
|
|
|
/// ```
|
|
|
|
|
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self::Point
|
|
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Scalar>,
|
|
|
|
|
J: IntoIterator,
|
2018-07-17 15:19:48 +00:00
|
|
|
J::Item: Borrow<Self::Point>,
|
|
|
|
|
Self::Point: Clone,
|
|
|
|
|
{
|
|
|
|
|
Self::optional_multiscalar_mul(
|
|
|
|
|
scalars,
|
2019-02-12 20:28:24 +00:00
|
|
|
points.into_iter().map(|P| Some(P.borrow().clone())),
|
|
|
|
|
)
|
2023-08-28 06:32:31 +00:00
|
|
|
.expect("should return some point")
|
2018-07-17 15:19:48 +00:00
|
|
|
}
|
2018-05-02 21:54:46 +00:00
|
|
|
}
|
|
|
|
|
|
2018-05-03 22:31:08 +00:00
|
|
|
/// A trait for variable-time multiscalar multiplication with precomputation.
|
|
|
|
|
///
|
|
|
|
|
/// A general multiscalar multiplication with precomputation can be written as
|
|
|
|
|
/// $$
|
|
|
|
|
/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m,
|
|
|
|
|
/// $$
|
|
|
|
|
/// where the \\(B_i\\) are *static* points, for which precomputation
|
|
|
|
|
/// is possible, and the \\(A_j\\) are *dynamic* points, for which
|
|
|
|
|
/// precomputation is not possible.
|
2019-02-12 20:28:24 +00:00
|
|
|
///
|
|
|
|
|
/// This trait has three methods for performing this computation:
|
|
|
|
|
///
|
2022-10-22 18:39:40 +00:00
|
|
|
/// * [`Self::vartime_multiscalar_mul`], which handles the special case where
|
|
|
|
|
/// \\(n = 0\\) and there are no dynamic points;
|
2019-02-12 20:28:24 +00:00
|
|
|
///
|
2022-10-22 18:39:40 +00:00
|
|
|
/// * [`Self::vartime_mixed_multiscalar_mul`], which takes the dynamic points as
|
|
|
|
|
/// already-validated `Point`s and is infallible;
|
2019-02-12 20:28:24 +00:00
|
|
|
///
|
2022-10-22 18:39:40 +00:00
|
|
|
/// * [`Self::optional_mixed_multiscalar_mul`], which takes the dynamic points
|
|
|
|
|
/// as `Option<Point>`s and returns an `Option<Point>`, allowing decompression
|
|
|
|
|
/// to be composed into the input iterators.
|
2019-02-12 20:28:24 +00:00
|
|
|
///
|
|
|
|
|
/// All methods require that the lengths of the input iterators be
|
2024-07-30 13:43:13 +00:00
|
|
|
/// known, as if they were `ExactSizeIterator`s. (It
|
2019-02-12 20:28:24 +00:00
|
|
|
/// does not require `ExactSizeIterator` only because that trait is
|
|
|
|
|
/// broken).
|
2018-05-03 22:31:08 +00:00
|
|
|
pub trait VartimePrecomputedMultiscalarMul: Sized {
|
|
|
|
|
/// The type of point to be multiplied, e.g., `RistrettoPoint`.
|
2019-02-12 20:28:24 +00:00
|
|
|
type Point: Clone;
|
2018-05-03 22:31:08 +00:00
|
|
|
|
|
|
|
|
/// Given the static points \\( B_i \\), perform precomputation
|
|
|
|
|
/// and return the precomputation data.
|
|
|
|
|
fn new<I>(static_points: I) -> Self
|
|
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Self::Point>;
|
|
|
|
|
|
2025-01-12 03:57:50 +00:00
|
|
|
/// Return the number of static points in the precomputation.
|
|
|
|
|
fn len(&self) -> usize;
|
|
|
|
|
|
|
|
|
|
/// Determine if the precomputation is empty.
|
|
|
|
|
fn is_empty(&self) -> bool;
|
|
|
|
|
|
2019-02-12 20:28:24 +00:00
|
|
|
/// Given `static_scalars`, an iterator of public scalars
|
|
|
|
|
/// \\(b_i\\), compute
|
|
|
|
|
/// $$
|
|
|
|
|
/// Q = b_1 B_1 + \cdots + b_m B_m,
|
|
|
|
|
/// $$
|
|
|
|
|
/// where the \\(B_j\\) are the points that were supplied to `new`.
|
|
|
|
|
///
|
2024-07-30 13:43:13 +00:00
|
|
|
/// It is valid for \\(b_i\\) to have a shorter length than \\(B_j\\).
|
|
|
|
|
/// In this case, any "unused" points are ignored in the computation.
|
|
|
|
|
/// It is an error to call this function if \\(b_i\\) has a longer
|
|
|
|
|
/// length than \\(B_j\\).
|
2019-02-12 20:28:24 +00:00
|
|
|
///
|
|
|
|
|
/// The trait bound aims for maximum flexibility: the input must
|
2025-06-04 15:40:10 +00:00
|
|
|
/// be convertible to iterators (`I: IntoIter`), and the
|
2019-02-12 20:28:24 +00:00
|
|
|
/// iterator's items must be `Borrow<Scalar>`, to allow iterators
|
|
|
|
|
/// returning either `Scalar`s or `&Scalar`s.
|
|
|
|
|
fn vartime_multiscalar_mul<I>(&self, static_scalars: I) -> Self::Point
|
|
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Scalar>,
|
|
|
|
|
{
|
|
|
|
|
use core::iter;
|
|
|
|
|
|
|
|
|
|
Self::vartime_mixed_multiscalar_mul(
|
|
|
|
|
self,
|
|
|
|
|
static_scalars,
|
|
|
|
|
iter::empty::<Scalar>(),
|
|
|
|
|
iter::empty::<Self::Point>(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-03 22:31:08 +00:00
|
|
|
/// Given `static_scalars`, an iterator of public scalars
|
|
|
|
|
/// \\(b_i\\), `dynamic_scalars`, an iterator of public scalars
|
|
|
|
|
/// \\(a_i\\), and `dynamic_points`, an iterator of points
|
|
|
|
|
/// \\(A_i\\), compute
|
|
|
|
|
/// $$
|
|
|
|
|
/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m,
|
|
|
|
|
/// $$
|
|
|
|
|
/// where the \\(B_j\\) are the points that were supplied to `new`.
|
|
|
|
|
///
|
2024-07-30 13:43:13 +00:00
|
|
|
/// It is valid for \\(b_i\\) to have a shorter length than \\(B_j\\).
|
|
|
|
|
/// In this case, any "unused" points are ignored in the computation.
|
|
|
|
|
/// It is an error to call this function if \\(b_i\\) has a longer
|
|
|
|
|
/// length than \\(B_j\\), or if \\(a_i\\) and \\(A_i\\) do not have
|
|
|
|
|
/// the same length.
|
2018-05-03 22:31:08 +00:00
|
|
|
///
|
|
|
|
|
/// The trait bound aims for maximum flexibility: the inputs must be
|
2025-06-04 15:40:10 +00:00
|
|
|
/// convertible to iterators (`I: IntoIter`), and the iterator's items
|
2018-05-03 22:31:08 +00:00
|
|
|
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
|
|
|
|
|
/// iterators returning either `Scalar`s or `&Scalar`s.
|
|
|
|
|
fn vartime_mixed_multiscalar_mul<I, J, K>(
|
|
|
|
|
&self,
|
|
|
|
|
static_scalars: I,
|
|
|
|
|
dynamic_scalars: J,
|
|
|
|
|
dynamic_points: K,
|
|
|
|
|
) -> Self::Point
|
|
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Scalar>,
|
|
|
|
|
J: IntoIterator,
|
|
|
|
|
J::Item: Borrow<Scalar>,
|
|
|
|
|
K: IntoIterator,
|
2019-02-12 20:28:24 +00:00
|
|
|
K::Item: Borrow<Self::Point>,
|
|
|
|
|
{
|
|
|
|
|
Self::optional_mixed_multiscalar_mul(
|
|
|
|
|
self,
|
|
|
|
|
static_scalars,
|
|
|
|
|
dynamic_scalars,
|
|
|
|
|
dynamic_points.into_iter().map(|P| Some(P.borrow().clone())),
|
|
|
|
|
)
|
2023-08-28 06:32:31 +00:00
|
|
|
.expect("should return some point")
|
2019-02-12 20:28:24 +00:00
|
|
|
}
|
2018-05-03 22:31:08 +00:00
|
|
|
|
|
|
|
|
/// Given `static_scalars`, an iterator of public scalars
|
2019-02-12 20:28:24 +00:00
|
|
|
/// \\(b_i\\), `dynamic_scalars`, an iterator of public scalars
|
|
|
|
|
/// \\(a_i\\), and `dynamic_points`, an iterator of points
|
|
|
|
|
/// \\(A_i\\), compute
|
2018-05-03 22:31:08 +00:00
|
|
|
/// $$
|
2019-02-12 20:28:24 +00:00
|
|
|
/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m,
|
2018-05-03 22:31:08 +00:00
|
|
|
/// $$
|
|
|
|
|
/// where the \\(B_j\\) are the points that were supplied to `new`.
|
|
|
|
|
///
|
2019-02-12 20:28:24 +00:00
|
|
|
/// If any of the dynamic points were `None`, return `None`.
|
|
|
|
|
///
|
2024-07-30 13:43:13 +00:00
|
|
|
/// It is valid for \\(b_i\\) to have a shorter length than \\(B_j\\).
|
|
|
|
|
/// In this case, any "unused" points are ignored in the computation.
|
|
|
|
|
/// It is an error to call this function if \\(b_i\\) has a longer
|
|
|
|
|
/// length than \\(B_j\\), or if \\(a_i\\) and \\(A_i\\) do not have
|
|
|
|
|
/// the same length.
|
2018-05-03 22:31:08 +00:00
|
|
|
///
|
2019-02-12 20:28:24 +00:00
|
|
|
/// This function is particularly useful when verifying statements
|
|
|
|
|
/// involving compressed points. Accepting `Option<Point>` allows
|
|
|
|
|
/// inlining point decompression into the multiscalar call,
|
|
|
|
|
/// avoiding the need for temporary buffers.
|
|
|
|
|
fn optional_mixed_multiscalar_mul<I, J, K>(
|
|
|
|
|
&self,
|
|
|
|
|
static_scalars: I,
|
|
|
|
|
dynamic_scalars: J,
|
|
|
|
|
dynamic_points: K,
|
|
|
|
|
) -> Option<Self::Point>
|
2018-05-03 22:31:08 +00:00
|
|
|
where
|
|
|
|
|
I: IntoIterator,
|
|
|
|
|
I::Item: Borrow<Scalar>,
|
2019-02-12 20:28:24 +00:00
|
|
|
J: IntoIterator,
|
|
|
|
|
J::Item: Borrow<Scalar>,
|
|
|
|
|
K: IntoIterator<Item = Option<Self::Point>>;
|
2018-05-03 22:31:08 +00:00
|
|
|
}
|
|
|
|
|
|
2017-11-17 01:34:28 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
// Private Traits
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/// Trait for checking whether a point is on the curve.
|
|
|
|
|
///
|
|
|
|
|
/// This trait is only for debugging/testing, since it should be
|
|
|
|
|
/// impossible for a `curve25519-dalek` user to construct an invalid
|
|
|
|
|
/// point.
|
2024-02-12 16:56:06 +00:00
|
|
|
#[allow(dead_code)]
|
2017-11-17 01:34:28 +00:00
|
|
|
pub(crate) trait ValidityCheck {
|
|
|
|
|
/// Checks whether the point is on the curve. Not CT.
|
|
|
|
|
fn is_valid(&self) -> bool;
|
|
|
|
|
}
|