mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-05 20:30:57 +00:00
Unfortunately, Rust selects `i32` as the type for an integer literal when the literal has no other type constraints. This means that someone cannot write `Scalar::from(1)`, as Rust will choose `i32` as the type for `1`, and we don't `impl From<i32> for Scalar`. We could implement `From` conversions for signed integers, but since `Scalar` operations should be constant-time by default, this would require us to extract the sign bit of the integer and use it to conditionally select between the positive and negative of Scalar constructed from the value bits. This is more expensive than the unsigned operation, and I don't think it's what anyone really wants. Making API consumers specify that their literals are unsigned is slightly annoying, but better than the above alternative. It would also be nice to change `Scalar::from_hash` to be `impl<D: Digest<OutputSize = U64>> From<D> for Scalar`, but this isn't currently allowed by Rust (since that `impl` "could" conflict with the `impl From<u8>` if someone decided that `u8` should `impl Digest`).
172 lines
5.6 KiB
Rust
172 lines
5.6 KiB
Rust
// -*- mode: rust; -*-
|
|
//
|
|
// This file is part of curve25519-dalek.
|
|
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
|
// See LICENSE for licensing information.
|
|
//
|
|
// Authors:
|
|
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
|
// - Henry de Valence <hdevalence@hdevalence.ca>
|
|
|
|
//! Module for common traits.
|
|
|
|
use core::borrow::Borrow;
|
|
|
|
use subtle;
|
|
|
|
use scalar::Scalar;
|
|
|
|
// ------------------------------------------------------------------------
|
|
// 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.
|
|
impl<T> IsIdentity for T
|
|
where
|
|
T: subtle::ConstantTimeEq + Identity,
|
|
{
|
|
fn is_identity(&self) -> bool {
|
|
self.ct_eq(&T::identity()).unwrap_u8() == 1u8
|
|
}
|
|
}
|
|
|
|
/// 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
|
|
/// convertable to iterators (`I: IntoIter`), and the iterator's items
|
|
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
|
|
/// iterators returning either `Scalar`s or `&Scalar`s.
|
|
///
|
|
/// ```
|
|
/// use curve25519_dalek::constants;
|
|
/// use curve25519_dalek::traits::MultiscalarMul;
|
|
/// use curve25519_dalek::ristretto::RistrettoPoint;
|
|
/// use curve25519_dalek::scalar::Scalar;
|
|
///
|
|
/// // Some scalars
|
|
/// let a = Scalar::from(87329482u64);
|
|
/// let b = Scalar::from(37264829u64);
|
|
/// let c = Scalar::from(98098098u64);
|
|
///
|
|
/// // 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());
|
|
/// ```
|
|
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;
|
|
|
|
/// 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
|
|
/// convertable to iterators (`I: IntoIter`), and the iterator's items
|
|
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
|
|
/// iterators returning either `Scalar`s or `&Scalar`s.
|
|
///
|
|
/// ```
|
|
/// use curve25519_dalek::constants;
|
|
/// use curve25519_dalek::traits::MultiscalarMul;
|
|
/// use curve25519_dalek::ristretto::RistrettoPoint;
|
|
/// use curve25519_dalek::scalar::Scalar;
|
|
///
|
|
/// // Some scalars
|
|
/// let a = Scalar::from(87329482u64);
|
|
/// let b = Scalar::from(37264829u64);
|
|
/// let c = Scalar::from(98098098u64);
|
|
///
|
|
/// // 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());
|
|
/// ```
|
|
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self::Point
|
|
where
|
|
I: IntoIterator,
|
|
I::Item: Borrow<Scalar>,
|
|
J: IntoIterator,
|
|
J::Item: Borrow<Self::Point>;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
// 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.
|
|
pub(crate) trait ValidityCheck {
|
|
/// Checks whether the point is on the curve. Not CT.
|
|
fn is_valid(&self) -> bool;
|
|
}
|